From 0c5c1ac1c25e279914b89e93b10ed75f0a530998 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sat, 16 Sep 2023 20:50:59 -0400 Subject: [PATCH 01/27] msg server handler + proto msg --- proto/stride/stakeibc/tx.proto | 12 ++++++++++++ x/stakeibc/handler.go | 3 +++ 2 files changed, 15 insertions(+) diff --git a/proto/stride/stakeibc/tx.proto b/proto/stride/stakeibc/tx.proto index d73a785298..e19b70d00e 100644 --- a/proto/stride/stakeibc/tx.proto +++ b/proto/stride/stakeibc/tx.proto @@ -28,6 +28,7 @@ service Msg { rpc UpdateValidatorSharesExchRate(MsgUpdateValidatorSharesExchRate) returns (MsgUpdateValidatorSharesExchRateResponse); rpc ClearBalance(MsgClearBalance) returns (MsgClearBalanceResponse); + rpc UndelegateHost(MsgUndelegateHost) returns (MsgUndelegateHost); } message MsgLiquidStake { @@ -151,3 +152,14 @@ message MsgUpdateValidatorSharesExchRate { string valoper = 3; } message MsgUpdateValidatorSharesExchRateResponse {} + +message MsgUndelegateHost { + string creator = 1; + string amount = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + +} +message MsgUndelegateHostResponse {} + diff --git a/x/stakeibc/handler.go b/x/stakeibc/handler.go index 1f5abd4090..f34eaec160 100644 --- a/x/stakeibc/handler.go +++ b/x/stakeibc/handler.go @@ -58,6 +58,9 @@ func NewMessageHandler(k keeper.Keeper) sdk.Handler { case *types.MsgUpdateValidatorSharesExchRate: res, err := msgServer.UpdateValidatorSharesExchRate(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgUndelegateHost: + res, err := msgServer.UndelegateHost(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) default: errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) return nil, errorsmod.Wrap(sdkerrors.ErrUnknownRequest, errMsg) From 75437284c562ae2575f1a1be7c38420ea5eb6803 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sat, 16 Sep 2023 20:54:22 -0400 Subject: [PATCH 02/27] make proto-gen --- x/stakeibc/types/tx.pb.go | 542 ++++++++++++++++++++++++++++++++------ 1 file changed, 458 insertions(+), 84 deletions(-) diff --git a/x/stakeibc/types/tx.pb.go b/x/stakeibc/types/tx.pb.go index e987b67adc..4b53c418b8 100644 --- a/x/stakeibc/types/tx.pb.go +++ b/x/stakeibc/types/tx.pb.go @@ -1184,6 +1184,87 @@ func (m *MsgUpdateValidatorSharesExchRateResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgUpdateValidatorSharesExchRateResponse proto.InternalMessageInfo +type MsgUndelegateHost struct { + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + Amount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,2,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"amount"` +} + +func (m *MsgUndelegateHost) Reset() { *m = MsgUndelegateHost{} } +func (m *MsgUndelegateHost) String() string { return proto.CompactTextString(m) } +func (*MsgUndelegateHost) ProtoMessage() {} +func (*MsgUndelegateHost) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7e09c9ad51cd54, []int{24} +} +func (m *MsgUndelegateHost) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUndelegateHost) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUndelegateHost.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 *MsgUndelegateHost) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUndelegateHost.Merge(m, src) +} +func (m *MsgUndelegateHost) XXX_Size() int { + return m.Size() +} +func (m *MsgUndelegateHost) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUndelegateHost.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUndelegateHost proto.InternalMessageInfo + +func (m *MsgUndelegateHost) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +type MsgUndelegateHostResponse struct { +} + +func (m *MsgUndelegateHostResponse) Reset() { *m = MsgUndelegateHostResponse{} } +func (m *MsgUndelegateHostResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUndelegateHostResponse) ProtoMessage() {} +func (*MsgUndelegateHostResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7e09c9ad51cd54, []int{25} +} +func (m *MsgUndelegateHostResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUndelegateHostResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUndelegateHostResponse.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 *MsgUndelegateHostResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUndelegateHostResponse.Merge(m, src) +} +func (m *MsgUndelegateHostResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUndelegateHostResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUndelegateHostResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUndelegateHostResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgLiquidStake)(nil), "stride.stakeibc.MsgLiquidStake") proto.RegisterType((*MsgLiquidStakeResponse)(nil), "stride.stakeibc.MsgLiquidStakeResponse") @@ -1209,95 +1290,99 @@ func init() { proto.RegisterType((*MsgRestoreInterchainAccountResponse)(nil), "stride.stakeibc.MsgRestoreInterchainAccountResponse") proto.RegisterType((*MsgUpdateValidatorSharesExchRate)(nil), "stride.stakeibc.MsgUpdateValidatorSharesExchRate") proto.RegisterType((*MsgUpdateValidatorSharesExchRateResponse)(nil), "stride.stakeibc.MsgUpdateValidatorSharesExchRateResponse") + proto.RegisterType((*MsgUndelegateHost)(nil), "stride.stakeibc.MsgUndelegateHost") + proto.RegisterType((*MsgUndelegateHostResponse)(nil), "stride.stakeibc.MsgUndelegateHostResponse") } func init() { proto.RegisterFile("stride/stakeibc/tx.proto", fileDescriptor_9b7e09c9ad51cd54) } var fileDescriptor_9b7e09c9ad51cd54 = []byte{ - // 1327 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0xcf, 0x36, 0x69, 0xea, 0xbe, 0x38, 0xff, 0x36, 0x69, 0xbb, 0xd9, 0x52, 0xdb, 0xdd, 0xf0, - 0x27, 0x14, 0x62, 0x2b, 0x69, 0x25, 0x44, 0x05, 0x87, 0x38, 0x29, 0xc2, 0x52, 0x53, 0xa1, 0x4d, - 0x4b, 0xa5, 0x4a, 0x68, 0x19, 0xef, 0x4c, 0xd7, 0xab, 0xee, 0xce, 0xb8, 0x3b, 0xeb, 0xe0, 0x72, - 0x40, 0x5c, 0x90, 0xb8, 0x20, 0x81, 0x90, 0x38, 0xa2, 0x1e, 0x38, 0x20, 0x71, 0x43, 0xfd, 0x10, - 0x3d, 0x56, 0x3d, 0x21, 0x0e, 0x16, 0x6a, 0x2f, 0x9c, 0xf3, 0x09, 0xd0, 0xce, 0xae, 0xc7, 0xbb, - 0xf6, 0xc6, 0x49, 0x5b, 0xd4, 0x53, 0xfc, 0xe6, 0xfd, 0xe6, 0xbd, 0xdf, 0x7b, 0xf3, 0xe6, 0xcd, - 0xcb, 0x82, 0xc6, 0xc3, 0xc0, 0xc5, 0xa4, 0xc6, 0x43, 0x74, 0x8f, 0xb8, 0x4d, 0xbb, 0x16, 0x76, - 0xab, 0xed, 0x80, 0x85, 0x4c, 0x9d, 0x8f, 0x35, 0xd5, 0xbe, 0x46, 0xbf, 0x38, 0x0c, 0x75, 0x6d, - 0x64, 0x21, 0xdb, 0x66, 0x1d, 0x1a, 0xc6, 0x7b, 0xf4, 0xf2, 0x30, 0x64, 0x1f, 0x79, 0x2e, 0x46, - 0x21, 0x0b, 0x12, 0xc0, 0xb2, 0xc3, 0x1c, 0x26, 0x7e, 0xd6, 0xa2, 0x5f, 0xc9, 0xea, 0x8a, 0xcd, - 0xb8, 0xcf, 0xb8, 0x15, 0x2b, 0x62, 0x21, 0x56, 0x19, 0x3f, 0x29, 0x30, 0xb7, 0xcb, 0x9d, 0xeb, - 0xee, 0xfd, 0x8e, 0x8b, 0xf7, 0x22, 0xb3, 0xaa, 0x06, 0xa7, 0xec, 0x80, 0x44, 0x46, 0x35, 0xa5, - 0xa2, 0xac, 0x9d, 0x36, 0xfb, 0xa2, 0xfa, 0x09, 0x4c, 0x23, 0x3f, 0xa2, 0xa3, 0x9d, 0x88, 0x14, - 0xf5, 0xea, 0xe3, 0x5e, 0x79, 0xe2, 0xef, 0x5e, 0xf9, 0x6d, 0xc7, 0x0d, 0x5b, 0x9d, 0x66, 0xd5, - 0x66, 0x7e, 0x62, 0x3d, 0xf9, 0xb3, 0xce, 0xf1, 0xbd, 0x5a, 0xf8, 0xa0, 0x4d, 0x78, 0xb5, 0x41, - 0x43, 0x33, 0xd9, 0xad, 0x5e, 0x00, 0x68, 0x31, 0x1e, 0x5a, 0x98, 0x50, 0xe6, 0x6b, 0x93, 0xc2, - 0xc9, 0xe9, 0x68, 0x65, 0x27, 0x5a, 0x30, 0x34, 0x38, 0x9b, 0xa5, 0x64, 0x12, 0xde, 0x66, 0x94, - 0x13, 0xe3, 0x37, 0x05, 0x16, 0x23, 0xd5, 0xde, 0xee, 0xeb, 0x25, 0xbc, 0x0e, 0x4b, 0x1e, 0xf7, - 0xad, 0x90, 0xdd, 0x23, 0xd4, 0x72, 0x9b, 0x76, 0x86, 0xf9, 0x82, 0xc7, 0xfd, 0x9b, 0x91, 0xa6, - 0xd1, 0xb4, 0xe3, 0x00, 0x6e, 0xc0, 0xca, 0x08, 0xcb, 0x7e, 0x0c, 0xea, 0x06, 0x2c, 0x87, 0x01, - 0xa2, 0x1c, 0xd9, 0xa1, 0xcb, 0xa8, 0x65, 0x33, 0xbf, 0xed, 0x91, 0x90, 0x08, 0xea, 0x05, 0x73, - 0x29, 0xa5, 0xdb, 0x4e, 0x54, 0xc6, 0xef, 0x0a, 0xcc, 0xef, 0x72, 0x67, 0xdb, 0x23, 0x28, 0xa8, - 0x23, 0x0f, 0x51, 0x7b, 0x5c, 0xd0, 0x2b, 0x50, 0xb0, 0x5b, 0xc8, 0xa5, 0x96, 0x8b, 0xe3, 0xb0, - 0xcd, 0x53, 0x42, 0x6e, 0xe0, 0x54, 0x3e, 0x26, 0x5f, 0x29, 0x1f, 0x91, 0xf3, 0x16, 0xa2, 0x94, - 0x78, 0xda, 0x94, 0xf4, 0x10, 0x89, 0xc6, 0x0a, 0x9c, 0x1b, 0x62, 0x2a, 0x0f, 0xef, 0x8f, 0xb8, - 0xd4, 0x4c, 0x82, 0x09, 0xf1, 0x5f, 0xd7, 0xc9, 0x9d, 0x07, 0x51, 0x58, 0xd6, 0xd7, 0x8c, 0x92, - 0xe4, 0xbc, 0x0a, 0xd1, 0xc2, 0x1d, 0x46, 0x89, 0xaa, 0x43, 0x21, 0x20, 0x36, 0x71, 0xf7, 0x49, - 0x90, 0xc4, 0x21, 0xe5, 0xa4, 0x08, 0x53, 0x64, 0x65, 0x1c, 0x7f, 0x9e, 0x84, 0x25, 0xa1, 0x72, - 0x5c, 0x1e, 0x92, 0xe0, 0xd3, 0xbe, 0xb5, 0x8f, 0x61, 0xd6, 0x66, 0x94, 0x92, 0xf8, 0x5c, 0xfb, - 0xc9, 0xaf, 0x6b, 0x07, 0xbd, 0xf2, 0xf2, 0x03, 0xe4, 0x7b, 0x57, 0x8d, 0x8c, 0xda, 0x30, 0x8b, - 0x03, 0xb9, 0x81, 0x55, 0x03, 0x8a, 0x4d, 0x62, 0xb7, 0x2e, 0x6f, 0xb6, 0x03, 0x72, 0xd7, 0xed, - 0x6a, 0x45, 0x41, 0x28, 0xb3, 0xa6, 0x5e, 0xc9, 0x5c, 0x1c, 0x41, 0xb9, 0x7e, 0xe6, 0xa0, 0x57, - 0x5e, 0x8c, 0xed, 0x0f, 0x74, 0x46, 0xea, 0x3e, 0xa9, 0x1b, 0x70, 0x7a, 0x50, 0xb3, 0x27, 0xc5, - 0xa6, 0xe5, 0x83, 0x5e, 0x79, 0x21, 0xde, 0x24, 0x55, 0x86, 0x59, 0x70, 0x93, 0x0a, 0x4e, 0x1f, - 0xcc, 0x74, 0xf6, 0x60, 0x6e, 0x40, 0x5c, 0xa2, 0x77, 0x49, 0x60, 0x25, 0x87, 0x1e, 0xc5, 0x0a, - 0xc2, 0x6c, 0xe9, 0xa0, 0x57, 0xd6, 0x63, 0xb3, 0x39, 0x20, 0xc3, 0x5c, 0xec, 0xaf, 0x6e, 0xc7, - 0x8b, 0xa2, 0x24, 0x17, 0x3a, 0xb4, 0xc9, 0x28, 0x76, 0xa9, 0x63, 0xb5, 0x49, 0xe0, 0x32, 0xac, - 0xcd, 0x54, 0x94, 0xb5, 0xa9, 0xfa, 0xf9, 0x83, 0x5e, 0xf9, 0x5c, 0x6c, 0x6c, 0x18, 0x61, 0x98, - 0xf3, 0x72, 0xe9, 0x33, 0xb1, 0xa2, 0x7a, 0xb0, 0xe4, 0xbb, 0xd4, 0x0a, 0x08, 0x26, 0x7e, 0x5b, - 0xa4, 0x38, 0x40, 0x21, 0xd1, 0x66, 0x05, 0xaf, 0x8f, 0x5e, 0xa0, 0x7a, 0x76, 0x88, 0xfd, 0xf4, - 0xd1, 0x3a, 0x24, 0x5d, 0x72, 0x87, 0xd8, 0xe6, 0xa2, 0xef, 0x52, 0x53, 0xda, 0x35, 0x51, 0x48, - 0x84, 0x37, 0xd4, 0x1d, 0xf1, 0x36, 0xf7, 0xbf, 0x78, 0x43, 0xdd, 0x21, 0x6f, 0x1f, 0x80, 0x16, - 0xb5, 0x1f, 0x4f, 0x74, 0x13, 0x4b, 0x34, 0x7f, 0x8b, 0x50, 0xd4, 0xf4, 0x08, 0xd6, 0xe6, 0x45, - 0xdb, 0x38, 0xe3, 0x71, 0x3f, 0xd5, 0x6c, 0xae, 0xc5, 0xca, 0xab, 0x85, 0xef, 0x1f, 0x96, 0x27, - 0xfe, 0x7d, 0x58, 0x9e, 0x30, 0x2e, 0xc0, 0xf9, 0x9c, 0x9a, 0x95, 0x35, 0xfd, 0x9d, 0x22, 0x5a, - 0xd6, 0xb6, 0x87, 0x5c, 0xff, 0x16, 0xc5, 0xc4, 0x23, 0x0e, 0x0a, 0x09, 0x16, 0x6d, 0x8d, 0x8f, - 0xb9, 0xa6, 0x15, 0x28, 0xca, 0xeb, 0x35, 0xe8, 0x37, 0xd0, 0xbf, 0x61, 0x0d, 0xac, 0x2e, 0xc3, - 0x49, 0xd2, 0x66, 0x76, 0x4b, 0x5c, 0xbe, 0x29, 0x33, 0x16, 0xd4, 0xb3, 0x30, 0xcd, 0x09, 0xc5, - 0xf2, 0xde, 0x25, 0x92, 0xb1, 0x0a, 0x17, 0x0f, 0xa5, 0x21, 0xc9, 0x86, 0xc9, 0xd5, 0x6c, 0xc6, - 0x0d, 0xe6, 0xf3, 0xfe, 0x1b, 0x38, 0x8e, 0x68, 0xa6, 0x0f, 0x9c, 0x18, 0xea, 0x03, 0xab, 0x30, - 0x4b, 0x3b, 0xbe, 0x15, 0xf4, 0x2d, 0x26, 0x5c, 0x8b, 0xb4, 0xe3, 0x4b, 0x2f, 0x46, 0x05, 0x4a, - 0xf9, 0x5e, 0xd3, 0x49, 0x5c, 0xd8, 0xe5, 0xce, 0x16, 0xc6, 0xaf, 0x4e, 0xe9, 0x2a, 0x80, 0x7c, - 0xdb, 0xb9, 0x36, 0x59, 0x99, 0x5c, 0x9b, 0xd9, 0xd4, 0xab, 0x43, 0x23, 0x43, 0x55, 0xfa, 0x31, - 0x53, 0x68, 0x43, 0x07, 0x6d, 0x98, 0x86, 0xe4, 0xf8, 0xab, 0x22, 0x94, 0xd1, 0xfd, 0x73, 0x06, - 0x31, 0xdc, 0x26, 0xae, 0xd3, 0x0a, 0x5f, 0x96, 0xeb, 0x65, 0x28, 0xec, 0x23, 0xcf, 0x42, 0x18, - 0x07, 0xc9, 0xbb, 0xa2, 0x3d, 0x7d, 0xb4, 0xbe, 0x9c, 0xd4, 0xf4, 0x16, 0xc6, 0x01, 0xe1, 0x7c, - 0x2f, 0x0c, 0x5c, 0xea, 0x98, 0xa7, 0xf6, 0x91, 0x17, 0xad, 0x44, 0x15, 0xf0, 0x95, 0xf0, 0x2a, - 0x2a, 0x60, 0xca, 0x4c, 0x24, 0xc3, 0x80, 0xca, 0x61, 0xfc, 0x64, 0x10, 0xdf, 0x2a, 0xa0, 0xee, - 0x72, 0x67, 0x87, 0x44, 0xaf, 0xa3, 0x04, 0xbd, 0x4e, 0xfa, 0xc6, 0x1b, 0xa0, 0x8f, 0x32, 0x90, - 0x04, 0x7f, 0x51, 0x92, 0xeb, 0xc6, 0x43, 0x16, 0x90, 0x06, 0x0d, 0x49, 0x20, 0x9e, 0xe0, 0xad, - 0x78, 0x9a, 0x7b, 0xb9, 0xc7, 0xbb, 0x0e, 0xc5, 0x64, 0x1a, 0xb4, 0xa2, 0xde, 0x21, 0xb8, 0xce, - 0x6d, 0x96, 0x47, 0x8a, 0xa2, 0xb1, 0xbd, 0x95, 0xf8, 0xb9, 0xf9, 0xa0, 0x4d, 0xcc, 0x19, 0x34, - 0x10, 0x8c, 0xb7, 0x60, 0x75, 0x0c, 0x2f, 0xc9, 0xff, 0xbe, 0x38, 0x84, 0x5b, 0x6d, 0x8c, 0x52, - 0xd1, 0xed, 0xb5, 0x50, 0x40, 0xf8, 0xb5, 0xae, 0xdd, 0x12, 0x4d, 0xe9, 0xa5, 0x62, 0xd0, 0x20, - 0xca, 0x20, 0x6b, 0x93, 0x24, 0xd5, 0x66, 0x5f, 0x34, 0x2e, 0xc1, 0xda, 0x51, 0x2e, 0xfb, 0xf4, - 0x36, 0x7f, 0x06, 0x98, 0xdc, 0xe5, 0x8e, 0x7a, 0x1b, 0x66, 0xd2, 0x73, 0xe0, 0x68, 0x2a, 0xb2, - 0x63, 0xa4, 0xfe, 0xce, 0x11, 0x00, 0x39, 0xa3, 0x7d, 0x09, 0x73, 0x43, 0x33, 0xa6, 0x91, 0xbb, - 0x35, 0x83, 0xd1, 0x2f, 0x1d, 0x8d, 0x91, 0x1e, 0x6e, 0xc3, 0x4c, 0x7a, 0x10, 0xca, 0xa5, 0x9e, - 0x02, 0xe4, 0x53, 0xcf, 0x99, 0x4e, 0xd4, 0xbb, 0xb0, 0x30, 0x32, 0x99, 0xbc, 0x99, 0xbf, 0x39, - 0x8b, 0xd2, 0xdf, 0x3f, 0x0e, 0x4a, 0xfa, 0xe9, 0xc2, 0xd9, 0x43, 0x5e, 0x8b, 0xdc, 0x34, 0xe4, - 0x63, 0xf5, 0xcd, 0xe3, 0x63, 0xa5, 0x67, 0x06, 0x4b, 0x79, 0xbd, 0xff, 0x90, 0x0c, 0x8d, 0x00, - 0xf5, 0xda, 0x31, 0x81, 0xd2, 0xe1, 0x17, 0x30, 0x9b, 0xed, 0xe9, 0x17, 0xf3, 0x2c, 0x64, 0x20, - 0xfa, 0xbb, 0x47, 0x42, 0xa4, 0xf9, 0x0e, 0x9c, 0xc9, 0x6f, 0xc7, 0xb9, 0x36, 0x72, 0xa1, 0xfa, - 0xc6, 0xb1, 0xa1, 0xd2, 0xad, 0x0d, 0xf3, 0xc3, 0x0d, 0x74, 0x35, 0xcf, 0xca, 0x10, 0x48, 0x7f, - 0xef, 0x18, 0x20, 0xe9, 0xe4, 0x1b, 0xd0, 0x0e, 0x6d, 0x82, 0x87, 0xd4, 0x5b, 0x3e, 0x5a, 0xbf, - 0xf2, 0x22, 0x68, 0xe9, 0xff, 0x07, 0x05, 0x2e, 0x8c, 0x6f, 0x63, 0xb9, 0x99, 0x1b, 0xbb, 0x45, - 0xff, 0xf0, 0x85, 0xb7, 0x48, 0x3e, 0x77, 0xa0, 0x98, 0xf9, 0x2f, 0xae, 0x92, 0x5f, 0xff, 0x03, - 0x84, 0xbe, 0x76, 0x14, 0xa2, 0x6f, 0xbb, 0x7e, 0xfd, 0xf1, 0xb3, 0x92, 0xf2, 0xe4, 0x59, 0x49, - 0xf9, 0xe7, 0x59, 0x49, 0xf9, 0xf1, 0x79, 0x69, 0xe2, 0xc9, 0xf3, 0xd2, 0xc4, 0x5f, 0xcf, 0x4b, - 0x13, 0x77, 0x36, 0x53, 0x83, 0xe8, 0x9e, 0xb0, 0xb6, 0x7e, 0x1d, 0x35, 0x79, 0x2d, 0xf9, 0x9a, - 0xb0, 0xbf, 0x71, 0xa5, 0xd6, 0x4d, 0x7d, 0xa1, 0x88, 0x06, 0xd3, 0xe6, 0xb4, 0xf8, 0x3e, 0x70, - 0xf9, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbc, 0xd4, 0x1b, 0x0b, 0xc1, 0x10, 0x00, 0x00, + // 1359 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x6f, 0xdc, 0x44, + 0x14, 0x8f, 0x9b, 0x34, 0xdd, 0xbe, 0x6c, 0xbe, 0x9c, 0xb4, 0x75, 0x1c, 0xba, 0xbb, 0x75, 0xf8, + 0x08, 0x85, 0xec, 0x2a, 0x69, 0x25, 0x44, 0x05, 0x87, 0x6c, 0x52, 0xc4, 0x4a, 0x4d, 0x85, 0x9c, + 0x96, 0xa2, 0x4a, 0xc8, 0xcc, 0x7a, 0xa6, 0x5e, 0xab, 0xf6, 0xcc, 0xd6, 0xe3, 0x0d, 0x5b, 0x0e, + 0x88, 0x0b, 0x12, 0x17, 0x24, 0xb8, 0x70, 0x44, 0x3d, 0x70, 0x40, 0xe2, 0x86, 0xfa, 0x47, 0xf4, + 0x58, 0xf5, 0x84, 0x38, 0xac, 0x50, 0x7b, 0xe1, 0xc2, 0x25, 0x7f, 0x01, 0xf2, 0xd8, 0x3b, 0x6b, + 0xef, 0x3a, 0x1f, 0x6d, 0xa1, 0xa7, 0xec, 0xcc, 0xfb, 0xcd, 0x7b, 0xbf, 0x37, 0xf3, 0xe6, 0x37, + 0x2f, 0x06, 0x8d, 0x87, 0x81, 0x8b, 0x49, 0x8d, 0x87, 0xe8, 0x2e, 0x71, 0x9b, 0x76, 0x2d, 0xec, + 0x56, 0xdb, 0x01, 0x0b, 0x99, 0x3a, 0x1b, 0x5b, 0xaa, 0x7d, 0x8b, 0x7e, 0x61, 0x18, 0xea, 0xda, + 0xc8, 0x42, 0xb6, 0xcd, 0x3a, 0x34, 0x8c, 0xd7, 0xe8, 0xe5, 0x61, 0xc8, 0x1e, 0xf2, 0x5c, 0x8c, + 0x42, 0x16, 0x24, 0x80, 0x45, 0x87, 0x39, 0x4c, 0xfc, 0xac, 0x45, 0xbf, 0x92, 0xd9, 0x25, 0x9b, + 0x71, 0x9f, 0x71, 0x2b, 0x36, 0xc4, 0x83, 0xd8, 0x64, 0xfc, 0xa8, 0xc0, 0xcc, 0x0e, 0x77, 0xae, + 0xb9, 0xf7, 0x3a, 0x2e, 0xde, 0x8d, 0xdc, 0xaa, 0x1a, 0x9c, 0xb2, 0x03, 0x12, 0x39, 0xd5, 0x94, + 0x8a, 0xb2, 0x7a, 0xda, 0xec, 0x0f, 0xd5, 0x8f, 0x60, 0x12, 0xf9, 0x11, 0x1d, 0xed, 0x44, 0x64, + 0xa8, 0x57, 0x1f, 0xf5, 0xca, 0x63, 0x7f, 0xf6, 0xca, 0x6f, 0x3a, 0x6e, 0xd8, 0xea, 0x34, 0xab, + 0x36, 0xf3, 0x13, 0xef, 0xc9, 0x9f, 0x35, 0x8e, 0xef, 0xd6, 0xc2, 0xfb, 0x6d, 0xc2, 0xab, 0x0d, + 0x1a, 0x9a, 0xc9, 0x6a, 0xf5, 0x3c, 0x40, 0x8b, 0xf1, 0xd0, 0xc2, 0x84, 0x32, 0x5f, 0x1b, 0x17, + 0x41, 0x4e, 0x47, 0x33, 0xdb, 0xd1, 0x84, 0xa1, 0xc1, 0xd9, 0x2c, 0x25, 0x93, 0xf0, 0x36, 0xa3, + 0x9c, 0x18, 0xbf, 0x28, 0x30, 0x1f, 0x99, 0x76, 0x77, 0x5e, 0x2d, 0xe1, 0x35, 0x58, 0xf0, 0xb8, + 0x6f, 0x85, 0xec, 0x2e, 0xa1, 0x96, 0xdb, 0xb4, 0x33, 0xcc, 0xe7, 0x3c, 0xee, 0xdf, 0x88, 0x2c, + 0x8d, 0xa6, 0x1d, 0x27, 0x70, 0x1d, 0x96, 0x46, 0x58, 0xf6, 0x73, 0x50, 0xd7, 0x61, 0x31, 0x0c, + 0x10, 0xe5, 0xc8, 0x0e, 0x5d, 0x46, 0x2d, 0x9b, 0xf9, 0x6d, 0x8f, 0x84, 0x44, 0x50, 0x2f, 0x98, + 0x0b, 0x29, 0xdb, 0x56, 0x62, 0x32, 0x7e, 0x55, 0x60, 0x76, 0x87, 0x3b, 0x5b, 0x1e, 0x41, 0x41, + 0x1d, 0x79, 0x88, 0xda, 0x87, 0x25, 0xbd, 0x04, 0x05, 0xbb, 0x85, 0x5c, 0x6a, 0xb9, 0x38, 0x4e, + 0xdb, 0x3c, 0x25, 0xc6, 0x0d, 0x9c, 0xda, 0x8f, 0xf1, 0x97, 0xda, 0x8f, 0x28, 0x78, 0x0b, 0x51, + 0x4a, 0x3c, 0x6d, 0x42, 0x46, 0x88, 0x86, 0xc6, 0x12, 0x9c, 0x1b, 0x62, 0x2a, 0x0f, 0xef, 0xb7, + 0xb8, 0xd4, 0x4c, 0x82, 0x09, 0xf1, 0x5f, 0xd5, 0xc9, 0x2d, 0x83, 0x28, 0x2c, 0xeb, 0x2b, 0x46, + 0x49, 0x72, 0x5e, 0x85, 0x68, 0xe2, 0x36, 0xa3, 0x44, 0xd5, 0xa1, 0x10, 0x10, 0x9b, 0xb8, 0x7b, + 0x24, 0x48, 0xf2, 0x90, 0xe3, 0xa4, 0x08, 0x53, 0x64, 0x65, 0x1e, 0xbf, 0x9f, 0x84, 0x05, 0x61, + 0x72, 0x5c, 0x1e, 0x92, 0xe0, 0xe3, 0xbe, 0xb7, 0x0f, 0x61, 0xda, 0x66, 0x94, 0x92, 0xf8, 0x5c, + 0xfb, 0x9b, 0x5f, 0xd7, 0xf6, 0x7b, 0xe5, 0xc5, 0xfb, 0xc8, 0xf7, 0xae, 0x18, 0x19, 0xb3, 0x61, + 0x16, 0x07, 0xe3, 0x06, 0x56, 0x0d, 0x28, 0x36, 0x89, 0xdd, 0xba, 0xb4, 0xd1, 0x0e, 0xc8, 0x1d, + 0xb7, 0xab, 0x15, 0x05, 0xa1, 0xcc, 0x9c, 0x7a, 0x39, 0x73, 0x71, 0x04, 0xe5, 0xfa, 0x99, 0xfd, + 0x5e, 0x79, 0x3e, 0xf6, 0x3f, 0xb0, 0x19, 0xa9, 0xfb, 0xa4, 0xae, 0xc3, 0xe9, 0x41, 0xcd, 0x9e, + 0x14, 0x8b, 0x16, 0xf7, 0x7b, 0xe5, 0xb9, 0x78, 0x91, 0x34, 0x19, 0x66, 0xc1, 0x4d, 0x2a, 0x38, + 0x7d, 0x30, 0x93, 0xd9, 0x83, 0xb9, 0x0e, 0x71, 0x89, 0xde, 0x21, 0x81, 0x95, 0x1c, 0x7a, 0x94, + 0x2b, 0x08, 0xb7, 0xa5, 0xfd, 0x5e, 0x59, 0x8f, 0xdd, 0xe6, 0x80, 0x0c, 0x73, 0xbe, 0x3f, 0xbb, + 0x15, 0x4f, 0x8a, 0x92, 0x9c, 0xeb, 0xd0, 0x26, 0xa3, 0xd8, 0xa5, 0x8e, 0xd5, 0x26, 0x81, 0xcb, + 0xb0, 0x36, 0x55, 0x51, 0x56, 0x27, 0xea, 0xcb, 0xfb, 0xbd, 0xf2, 0xb9, 0xd8, 0xd9, 0x30, 0xc2, + 0x30, 0x67, 0xe5, 0xd4, 0x27, 0x62, 0x46, 0xf5, 0x60, 0xc1, 0x77, 0xa9, 0x15, 0x10, 0x4c, 0xfc, + 0xb6, 0xd8, 0xe2, 0x00, 0x85, 0x44, 0x9b, 0x16, 0xbc, 0x3e, 0x78, 0x8e, 0xea, 0xd9, 0x26, 0xf6, + 0x93, 0x87, 0x6b, 0x90, 0xa8, 0xe4, 0x36, 0xb1, 0xcd, 0x79, 0xdf, 0xa5, 0xa6, 0xf4, 0x6b, 0xa2, + 0x90, 0x88, 0x68, 0xa8, 0x3b, 0x12, 0x6d, 0xe6, 0x3f, 0x89, 0x86, 0xba, 0x43, 0xd1, 0xde, 0x03, + 0x2d, 0x92, 0x1f, 0x4f, 0xa8, 0x89, 0x25, 0xc4, 0xdf, 0x22, 0x14, 0x35, 0x3d, 0x82, 0xb5, 0x59, + 0x21, 0x1b, 0x67, 0x3c, 0xee, 0xa7, 0xc4, 0xe6, 0x6a, 0x6c, 0xbc, 0x52, 0xf8, 0xee, 0x41, 0x79, + 0xec, 0xef, 0x07, 0xe5, 0x31, 0xe3, 0x3c, 0x2c, 0xe7, 0xd4, 0xac, 0xac, 0xe9, 0x6f, 0x15, 0x21, + 0x59, 0x5b, 0x1e, 0x72, 0xfd, 0x9b, 0x14, 0x13, 0x8f, 0x38, 0x28, 0x24, 0x58, 0xc8, 0x1a, 0x3f, + 0xe4, 0x9a, 0x56, 0xa0, 0x28, 0xaf, 0xd7, 0x40, 0x6f, 0xa0, 0x7f, 0xc3, 0x1a, 0x58, 0x5d, 0x84, + 0x93, 0xa4, 0xcd, 0xec, 0x96, 0xb8, 0x7c, 0x13, 0x66, 0x3c, 0x50, 0xcf, 0xc2, 0x24, 0x27, 0x14, + 0xcb, 0x7b, 0x97, 0x8c, 0x8c, 0x15, 0xb8, 0x70, 0x20, 0x0d, 0x49, 0x36, 0x4c, 0xae, 0x66, 0x33, + 0x16, 0x98, 0x4f, 0xfb, 0x6f, 0xe0, 0x61, 0x44, 0x33, 0x3a, 0x70, 0x62, 0x48, 0x07, 0x56, 0x60, + 0x9a, 0x76, 0x7c, 0x2b, 0xe8, 0x7b, 0x4c, 0xb8, 0x16, 0x69, 0xc7, 0x97, 0x51, 0x8c, 0x0a, 0x94, + 0xf2, 0xa3, 0xa6, 0x37, 0x71, 0x6e, 0x87, 0x3b, 0x9b, 0x18, 0xbf, 0x3c, 0xa5, 0x2b, 0x00, 0xf2, + 0x6d, 0xe7, 0xda, 0x78, 0x65, 0x7c, 0x75, 0x6a, 0x43, 0xaf, 0x0e, 0xb5, 0x0c, 0x55, 0x19, 0xc7, + 0x4c, 0xa1, 0x0d, 0x1d, 0xb4, 0x61, 0x1a, 0x92, 0xe3, 0xcf, 0x8a, 0x30, 0x46, 0xf7, 0xcf, 0x19, + 0xe4, 0x70, 0x8b, 0xb8, 0x4e, 0x2b, 0x7c, 0x51, 0xae, 0x97, 0xa0, 0xb0, 0x87, 0x3c, 0x0b, 0x61, + 0x1c, 0x24, 0xef, 0x8a, 0xf6, 0xe4, 0xe1, 0xda, 0x62, 0x52, 0xd3, 0x9b, 0x18, 0x07, 0x84, 0xf3, + 0xdd, 0x30, 0x70, 0xa9, 0x63, 0x9e, 0xda, 0x43, 0x5e, 0x34, 0x13, 0x55, 0xc0, 0x97, 0x22, 0xaa, + 0xa8, 0x80, 0x09, 0x33, 0x19, 0x19, 0x06, 0x54, 0x0e, 0xe2, 0x27, 0x93, 0xf8, 0x46, 0x01, 0x75, + 0x87, 0x3b, 0xdb, 0x24, 0x7a, 0x1d, 0x25, 0xe8, 0x55, 0xd2, 0x37, 0x5e, 0x03, 0x7d, 0x94, 0x81, + 0x24, 0xf8, 0x93, 0x92, 0x5c, 0x37, 0x1e, 0xb2, 0x80, 0x34, 0x68, 0x48, 0x02, 0xf1, 0x04, 0x6f, + 0xc6, 0xdd, 0xdc, 0x8b, 0x3d, 0xde, 0x75, 0x28, 0x26, 0xdd, 0xa0, 0x15, 0x69, 0x87, 0xe0, 0x3a, + 0xb3, 0x51, 0x1e, 0x29, 0x8a, 0xc6, 0xd6, 0x66, 0x12, 0xe7, 0xc6, 0xfd, 0x36, 0x31, 0xa7, 0xd0, + 0x60, 0x60, 0xbc, 0x01, 0x2b, 0x87, 0xf0, 0x92, 0xfc, 0xef, 0x89, 0x43, 0xb8, 0xd9, 0xc6, 0x28, + 0x95, 0xdd, 0x6e, 0x0b, 0x05, 0x84, 0x5f, 0xed, 0xda, 0x2d, 0x21, 0x4a, 0x2f, 0x94, 0x83, 0x06, + 0xd1, 0x0e, 0xb2, 0x36, 0x49, 0xb6, 0xda, 0xec, 0x0f, 0x8d, 0x8b, 0xb0, 0x7a, 0x54, 0x48, 0x49, + 0xaf, 0x23, 0xba, 0xc0, 0x81, 0x40, 0x44, 0x72, 0xf6, 0xff, 0xf7, 0x12, 0xc6, 0xb2, 0xd0, 0xc8, + 0x6c, 0xd8, 0x3e, 0xa7, 0x8d, 0x7f, 0x00, 0xc6, 0x77, 0xb8, 0xa3, 0xde, 0x82, 0xa9, 0x74, 0x6f, + 0x3a, 0x7a, 0x3c, 0xd9, 0xd6, 0x56, 0x7f, 0xeb, 0x08, 0x80, 0xec, 0x1b, 0xbf, 0x80, 0x99, 0xa1, + 0xbe, 0xd7, 0xc8, 0x5d, 0x9a, 0xc1, 0xe8, 0x17, 0x8f, 0xc6, 0xc8, 0x08, 0xb7, 0x60, 0x2a, 0xdd, + 0x9c, 0xe5, 0x52, 0x4f, 0x01, 0xf2, 0xa9, 0xe7, 0x74, 0x4c, 0xea, 0x1d, 0x98, 0x1b, 0xe9, 0x96, + 0x5e, 0xcf, 0x5f, 0x9c, 0x45, 0xe9, 0xef, 0x1e, 0x07, 0x25, 0xe3, 0x74, 0xe1, 0xec, 0x01, 0x2f, + 0x58, 0xee, 0x36, 0xe4, 0x63, 0xf5, 0x8d, 0xe3, 0x63, 0x65, 0x64, 0x06, 0x0b, 0x79, 0xef, 0xd1, + 0x01, 0x3b, 0x34, 0x02, 0xd4, 0x6b, 0xc7, 0x04, 0xca, 0x80, 0x9f, 0xc3, 0x74, 0xf6, 0x9d, 0xb9, + 0x90, 0xe7, 0x21, 0x03, 0xd1, 0xdf, 0x3e, 0x12, 0x22, 0xdd, 0x77, 0xe0, 0x4c, 0xfe, 0x13, 0x91, + 0xeb, 0x23, 0x17, 0xaa, 0xaf, 0x1f, 0x1b, 0x2a, 0xc3, 0xda, 0x30, 0x3b, 0x2c, 0xea, 0x2b, 0x79, + 0x5e, 0x86, 0x40, 0xfa, 0x3b, 0xc7, 0x00, 0xc9, 0x20, 0x5f, 0x83, 0x76, 0xa0, 0x30, 0x1f, 0x50, + 0x6f, 0xf9, 0x68, 0xfd, 0xf2, 0xf3, 0xa0, 0x65, 0xfc, 0xef, 0x15, 0x38, 0x7f, 0xb8, 0xb4, 0xe6, + 0xee, 0xdc, 0xa1, 0x4b, 0xf4, 0xf7, 0x9f, 0x7b, 0x89, 0xe4, 0x73, 0x1b, 0x8a, 0x99, 0xff, 0x2c, + 0x2b, 0xf9, 0xf5, 0x3f, 0x40, 0xe8, 0xab, 0x47, 0x21, 0xa4, 0xef, 0xcf, 0x60, 0x66, 0x48, 0xa6, + 0x73, 0x45, 0x2b, 0x8b, 0xd1, 0x8f, 0x81, 0xa9, 0x5f, 0x7b, 0xf4, 0xb4, 0xa4, 0x3c, 0x7e, 0x5a, + 0x52, 0xfe, 0x7a, 0x5a, 0x52, 0x7e, 0x78, 0x56, 0x1a, 0x7b, 0xfc, 0xac, 0x34, 0xf6, 0xc7, 0xb3, + 0xd2, 0xd8, 0xed, 0x8d, 0x94, 0xac, 0xef, 0x0a, 0x3f, 0x6b, 0xd7, 0x50, 0x93, 0xd7, 0x92, 0x6f, + 0x27, 0x7b, 0xeb, 0x97, 0x6b, 0xdd, 0xd4, 0xf7, 0x98, 0x48, 0xe6, 0x9b, 0x93, 0xe2, 0x6b, 0xc8, + 0xa5, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x9d, 0xb5, 0x94, 0xe8, 0xaf, 0x11, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1324,6 +1409,7 @@ type MsgClient interface { RestoreInterchainAccount(ctx context.Context, in *MsgRestoreInterchainAccount, opts ...grpc.CallOption) (*MsgRestoreInterchainAccountResponse, error) UpdateValidatorSharesExchRate(ctx context.Context, in *MsgUpdateValidatorSharesExchRate, opts ...grpc.CallOption) (*MsgUpdateValidatorSharesExchRateResponse, error) ClearBalance(ctx context.Context, in *MsgClearBalance, opts ...grpc.CallOption) (*MsgClearBalanceResponse, error) + UndelegateHost(ctx context.Context, in *MsgUndelegateHost, opts ...grpc.CallOption) (*MsgUndelegateHost, error) } type msgClient struct { @@ -1442,6 +1528,15 @@ func (c *msgClient) ClearBalance(ctx context.Context, in *MsgClearBalance, opts return out, nil } +func (c *msgClient) UndelegateHost(ctx context.Context, in *MsgUndelegateHost, opts ...grpc.CallOption) (*MsgUndelegateHost, error) { + out := new(MsgUndelegateHost) + err := c.cc.Invoke(ctx, "/stride.stakeibc.Msg/UndelegateHost", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { LiquidStake(context.Context, *MsgLiquidStake) (*MsgLiquidStakeResponse, error) @@ -1456,6 +1551,7 @@ type MsgServer interface { RestoreInterchainAccount(context.Context, *MsgRestoreInterchainAccount) (*MsgRestoreInterchainAccountResponse, error) UpdateValidatorSharesExchRate(context.Context, *MsgUpdateValidatorSharesExchRate) (*MsgUpdateValidatorSharesExchRateResponse, error) ClearBalance(context.Context, *MsgClearBalance) (*MsgClearBalanceResponse, error) + UndelegateHost(context.Context, *MsgUndelegateHost) (*MsgUndelegateHost, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -1498,6 +1594,9 @@ func (*UnimplementedMsgServer) UpdateValidatorSharesExchRate(ctx context.Context func (*UnimplementedMsgServer) ClearBalance(ctx context.Context, req *MsgClearBalance) (*MsgClearBalanceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ClearBalance not implemented") } +func (*UnimplementedMsgServer) UndelegateHost(ctx context.Context, req *MsgUndelegateHost) (*MsgUndelegateHost, error) { + return nil, status.Errorf(codes.Unimplemented, "method UndelegateHost not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -1719,6 +1818,24 @@ func _Msg_ClearBalance_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } +func _Msg_UndelegateHost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUndelegateHost) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UndelegateHost(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/stride.stakeibc.Msg/UndelegateHost", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UndelegateHost(ctx, req.(*MsgUndelegateHost)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "stride.stakeibc.Msg", HandlerType: (*MsgServer)(nil), @@ -1771,6 +1888,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "ClearBalance", Handler: _Msg_ClearBalance_Handler, }, + { + MethodName: "UndelegateHost", + Handler: _Msg_UndelegateHost_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "stride/stakeibc/tx.proto", @@ -2685,6 +2806,69 @@ func (m *MsgUpdateValidatorSharesExchRateResponse) MarshalToSizedBuffer(dAtA []b return len(dAtA) - i, nil } +func (m *MsgUndelegateHost) 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 *MsgUndelegateHost) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUndelegateHost) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.Amount.Size() + i -= size + if _, err := m.Amount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintTx(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUndelegateHostResponse) 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 *MsgUndelegateHostResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUndelegateHostResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -3087,6 +3271,30 @@ func (m *MsgUpdateValidatorSharesExchRateResponse) Size() (n int) { return n } +func (m *MsgUndelegateHost) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUndelegateHostResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -5754,6 +5962,172 @@ func (m *MsgUpdateValidatorSharesExchRateResponse) Unmarshal(dAtA []byte) error } return nil } +func (m *MsgUndelegateHost) 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: MsgUndelegateHost: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUndelegateHost: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", 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.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", 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 + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + 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 *MsgUndelegateHostResponse) 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: MsgUndelegateHostResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUndelegateHostResponse: 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 skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 From 073791f4e94ff30ca412987fee83d238cbf28f1a Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sat, 16 Sep 2023 21:13:20 -0400 Subject: [PATCH 03/27] add msg server, undelegate host msg, cli tx and admin gate --- proto/stride/stakeibc/tx.proto | 2 +- x/stakeibc/client/cli/tx.go | 1 + x/stakeibc/client/cli/tx_undelegate_host.go | 49 ++++++ x/stakeibc/keeper/msg_undelegate_host.go | 19 +++ x/stakeibc/types/codec.go | 2 + x/stakeibc/types/message_undelegate_host.go | 53 ++++++ x/stakeibc/types/tx.pb.go | 180 ++++++++++---------- 7 files changed, 215 insertions(+), 91 deletions(-) create mode 100644 x/stakeibc/client/cli/tx_undelegate_host.go create mode 100644 x/stakeibc/keeper/msg_undelegate_host.go create mode 100644 x/stakeibc/types/message_undelegate_host.go diff --git a/proto/stride/stakeibc/tx.proto b/proto/stride/stakeibc/tx.proto index e19b70d00e..d93cc6c41c 100644 --- a/proto/stride/stakeibc/tx.proto +++ b/proto/stride/stakeibc/tx.proto @@ -28,7 +28,7 @@ service Msg { rpc UpdateValidatorSharesExchRate(MsgUpdateValidatorSharesExchRate) returns (MsgUpdateValidatorSharesExchRateResponse); rpc ClearBalance(MsgClearBalance) returns (MsgClearBalanceResponse); - rpc UndelegateHost(MsgUndelegateHost) returns (MsgUndelegateHost); + rpc UndelegateHost(MsgUndelegateHost) returns (MsgUndelegateHostResponse); } message MsgLiquidStake { diff --git a/x/stakeibc/client/cli/tx.go b/x/stakeibc/client/cli/tx.go index 4ac08a0077..ddf06cb335 100644 --- a/x/stakeibc/client/cli/tx.go +++ b/x/stakeibc/client/cli/tx.go @@ -36,6 +36,7 @@ func GetTxCmd() *cobra.Command { cmd.AddCommand(CmdRestoreInterchainAccount()) cmd.AddCommand(CmdUpdateValidatorSharesExchRate()) cmd.AddCommand(CmdClearBalance()) + cmd.AddCommand(CmdUndelegateHost()) return cmd } diff --git a/x/stakeibc/client/cli/tx_undelegate_host.go b/x/stakeibc/client/cli/tx_undelegate_host.go new file mode 100644 index 0000000000..f928937d35 --- /dev/null +++ b/x/stakeibc/client/cli/tx_undelegate_host.go @@ -0,0 +1,49 @@ +package cli + +import ( + "strconv" + + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/spf13/cobra" + + "github.com/Stride-Labs/stride/v14/x/stakeibc/types" +) + +var _ = strconv.Itoa(0) + +func CmdUndelegateHost() *cobra.Command { + cmd := &cobra.Command{ + Use: "undelegate-host [amount]", + Short: "Broadcast message undelegate-host", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + argAmount, found := sdk.NewIntFromString(args[0]) + if !found { + return errorsmod.Wrap(sdkerrors.ErrInvalidType, "can not convert string to int") + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msg := types.NewMsgUndelegateHost( + clientCtx.GetFromAddress().String(), + argAmount, + ) + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/stakeibc/keeper/msg_undelegate_host.go b/x/stakeibc/keeper/msg_undelegate_host.go new file mode 100644 index 0000000000..ac1988df61 --- /dev/null +++ b/x/stakeibc/keeper/msg_undelegate_host.go @@ -0,0 +1,19 @@ +package keeper + +import ( + "context" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Stride-Labs/stride/v14/x/stakeibc/types" +) + +func (k msgServer) UndelegateHost(goCtx context.Context, msg *types.MsgUndelegateHost) (*types.MsgUndelegateHostResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // log: issuing an undelegation to Evmos + k.Logger(ctx).Info(fmt.Sprintf("Issuing an undelegation to Evmos")) + + return &types.MsgUndelegateHostResponse{}, nil +} diff --git a/x/stakeibc/types/codec.go b/x/stakeibc/types/codec.go index 857737d6ba..e9028310fe 100644 --- a/x/stakeibc/types/codec.go +++ b/x/stakeibc/types/codec.go @@ -23,6 +23,7 @@ func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&ToggleLSMProposal{}, "stakeibc/ToggleLSMProposal", nil) cdc.RegisterConcrete(&MsgRestoreInterchainAccount{}, "stakeibc/RestoreInterchainAccount", nil) cdc.RegisterConcrete(&MsgUpdateValidatorSharesExchRate{}, "stakeibc/UpdateValidatorSharesExchRate", nil) + cdc.RegisterConcrete(&MsgUndelegateHost{}, "stakeibc/UndelegateHost", nil) // this line is used by starport scaffolding # 2 } @@ -39,6 +40,7 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { &MsgDeleteValidator{}, &MsgRestoreInterchainAccount{}, &MsgUpdateValidatorSharesExchRate{}, + &MsgUndelegateHost{}, ) registry.RegisterImplementations((*govtypes.Content)(nil), diff --git a/x/stakeibc/types/message_undelegate_host.go b/x/stakeibc/types/message_undelegate_host.go new file mode 100644 index 0000000000..3a045e28b5 --- /dev/null +++ b/x/stakeibc/types/message_undelegate_host.go @@ -0,0 +1,53 @@ +package types + +import ( + errorsmod "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/Stride-Labs/stride/v14/utils" +) + +const TypeMsgUndelegateHost = "undelegate_host" + +var _ sdk.Msg = &MsgUndelegateHost{} + +func NewMsgUndelegateHost(creator string, amount sdkmath.Int) *MsgUndelegateHost { + return &MsgUndelegateHost{ + Creator: creator, + Amount: amount, + } +} + +func (msg *MsgUndelegateHost) Route() string { + return RouterKey +} + +func (msg *MsgUndelegateHost) Type() string { + return TypeMsgUndelegateHost +} + +func (msg *MsgUndelegateHost) GetSigners() []sdk.AccAddress { + creator, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + panic(err) + } + return []sdk.AccAddress{creator} +} + +func (msg *MsgUndelegateHost) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg *MsgUndelegateHost) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) + } + if err := utils.ValidateAdminAddress(msg.Creator); err != nil { + return err + } + return nil +} diff --git a/x/stakeibc/types/tx.pb.go b/x/stakeibc/types/tx.pb.go index 4b53c418b8..1a7034fd3b 100644 --- a/x/stakeibc/types/tx.pb.go +++ b/x/stakeibc/types/tx.pb.go @@ -1298,91 +1298,91 @@ func init() { proto.RegisterFile("stride/stakeibc/tx.proto", fileDescriptor_9b7e var fileDescriptor_9b7e09c9ad51cd54 = []byte{ // 1359 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x6f, 0xdc, 0x44, - 0x14, 0x8f, 0x9b, 0x34, 0xdd, 0xbe, 0x6c, 0xbe, 0x9c, 0xb4, 0x75, 0x1c, 0xba, 0xbb, 0x75, 0xf8, - 0x08, 0x85, 0xec, 0x2a, 0x69, 0x25, 0x44, 0x05, 0x87, 0x6c, 0x52, 0xc4, 0x4a, 0x4d, 0x85, 0x9c, - 0x96, 0xa2, 0x4a, 0xc8, 0xcc, 0x7a, 0xa6, 0x5e, 0xab, 0xf6, 0xcc, 0xd6, 0xe3, 0x0d, 0x5b, 0x0e, - 0x88, 0x0b, 0x12, 0x17, 0x24, 0xb8, 0x70, 0x44, 0x3d, 0x70, 0x40, 0xe2, 0x86, 0xfa, 0x47, 0xf4, - 0x58, 0xf5, 0x84, 0x38, 0xac, 0x50, 0x7b, 0xe1, 0xc2, 0x25, 0x7f, 0x01, 0xf2, 0xd8, 0x3b, 0x6b, - 0xef, 0x3a, 0x1f, 0x6d, 0xa1, 0xa7, 0xec, 0xcc, 0xfb, 0xcd, 0x7b, 0xbf, 0x37, 0xf3, 0xe6, 0x37, - 0x2f, 0x06, 0x8d, 0x87, 0x81, 0x8b, 0x49, 0x8d, 0x87, 0xe8, 0x2e, 0x71, 0x9b, 0x76, 0x2d, 0xec, - 0x56, 0xdb, 0x01, 0x0b, 0x99, 0x3a, 0x1b, 0x5b, 0xaa, 0x7d, 0x8b, 0x7e, 0x61, 0x18, 0xea, 0xda, - 0xc8, 0x42, 0xb6, 0xcd, 0x3a, 0x34, 0x8c, 0xd7, 0xe8, 0xe5, 0x61, 0xc8, 0x1e, 0xf2, 0x5c, 0x8c, - 0x42, 0x16, 0x24, 0x80, 0x45, 0x87, 0x39, 0x4c, 0xfc, 0xac, 0x45, 0xbf, 0x92, 0xd9, 0x25, 0x9b, - 0x71, 0x9f, 0x71, 0x2b, 0x36, 0xc4, 0x83, 0xd8, 0x64, 0xfc, 0xa8, 0xc0, 0xcc, 0x0e, 0x77, 0xae, - 0xb9, 0xf7, 0x3a, 0x2e, 0xde, 0x8d, 0xdc, 0xaa, 0x1a, 0x9c, 0xb2, 0x03, 0x12, 0x39, 0xd5, 0x94, - 0x8a, 0xb2, 0x7a, 0xda, 0xec, 0x0f, 0xd5, 0x8f, 0x60, 0x12, 0xf9, 0x11, 0x1d, 0xed, 0x44, 0x64, - 0xa8, 0x57, 0x1f, 0xf5, 0xca, 0x63, 0x7f, 0xf6, 0xca, 0x6f, 0x3a, 0x6e, 0xd8, 0xea, 0x34, 0xab, - 0x36, 0xf3, 0x13, 0xef, 0xc9, 0x9f, 0x35, 0x8e, 0xef, 0xd6, 0xc2, 0xfb, 0x6d, 0xc2, 0xab, 0x0d, - 0x1a, 0x9a, 0xc9, 0x6a, 0xf5, 0x3c, 0x40, 0x8b, 0xf1, 0xd0, 0xc2, 0x84, 0x32, 0x5f, 0x1b, 0x17, - 0x41, 0x4e, 0x47, 0x33, 0xdb, 0xd1, 0x84, 0xa1, 0xc1, 0xd9, 0x2c, 0x25, 0x93, 0xf0, 0x36, 0xa3, - 0x9c, 0x18, 0xbf, 0x28, 0x30, 0x1f, 0x99, 0x76, 0x77, 0x5e, 0x2d, 0xe1, 0x35, 0x58, 0xf0, 0xb8, - 0x6f, 0x85, 0xec, 0x2e, 0xa1, 0x96, 0xdb, 0xb4, 0x33, 0xcc, 0xe7, 0x3c, 0xee, 0xdf, 0x88, 0x2c, - 0x8d, 0xa6, 0x1d, 0x27, 0x70, 0x1d, 0x96, 0x46, 0x58, 0xf6, 0x73, 0x50, 0xd7, 0x61, 0x31, 0x0c, - 0x10, 0xe5, 0xc8, 0x0e, 0x5d, 0x46, 0x2d, 0x9b, 0xf9, 0x6d, 0x8f, 0x84, 0x44, 0x50, 0x2f, 0x98, - 0x0b, 0x29, 0xdb, 0x56, 0x62, 0x32, 0x7e, 0x55, 0x60, 0x76, 0x87, 0x3b, 0x5b, 0x1e, 0x41, 0x41, - 0x1d, 0x79, 0x88, 0xda, 0x87, 0x25, 0xbd, 0x04, 0x05, 0xbb, 0x85, 0x5c, 0x6a, 0xb9, 0x38, 0x4e, - 0xdb, 0x3c, 0x25, 0xc6, 0x0d, 0x9c, 0xda, 0x8f, 0xf1, 0x97, 0xda, 0x8f, 0x28, 0x78, 0x0b, 0x51, - 0x4a, 0x3c, 0x6d, 0x42, 0x46, 0x88, 0x86, 0xc6, 0x12, 0x9c, 0x1b, 0x62, 0x2a, 0x0f, 0xef, 0xb7, - 0xb8, 0xd4, 0x4c, 0x82, 0x09, 0xf1, 0x5f, 0xd5, 0xc9, 0x2d, 0x83, 0x28, 0x2c, 0xeb, 0x2b, 0x46, - 0x49, 0x72, 0x5e, 0x85, 0x68, 0xe2, 0x36, 0xa3, 0x44, 0xd5, 0xa1, 0x10, 0x10, 0x9b, 0xb8, 0x7b, - 0x24, 0x48, 0xf2, 0x90, 0xe3, 0xa4, 0x08, 0x53, 0x64, 0x65, 0x1e, 0xbf, 0x9f, 0x84, 0x05, 0x61, - 0x72, 0x5c, 0x1e, 0x92, 0xe0, 0xe3, 0xbe, 0xb7, 0x0f, 0x61, 0xda, 0x66, 0x94, 0x92, 0xf8, 0x5c, - 0xfb, 0x9b, 0x5f, 0xd7, 0xf6, 0x7b, 0xe5, 0xc5, 0xfb, 0xc8, 0xf7, 0xae, 0x18, 0x19, 0xb3, 0x61, - 0x16, 0x07, 0xe3, 0x06, 0x56, 0x0d, 0x28, 0x36, 0x89, 0xdd, 0xba, 0xb4, 0xd1, 0x0e, 0xc8, 0x1d, - 0xb7, 0xab, 0x15, 0x05, 0xa1, 0xcc, 0x9c, 0x7a, 0x39, 0x73, 0x71, 0x04, 0xe5, 0xfa, 0x99, 0xfd, - 0x5e, 0x79, 0x3e, 0xf6, 0x3f, 0xb0, 0x19, 0xa9, 0xfb, 0xa4, 0xae, 0xc3, 0xe9, 0x41, 0xcd, 0x9e, - 0x14, 0x8b, 0x16, 0xf7, 0x7b, 0xe5, 0xb9, 0x78, 0x91, 0x34, 0x19, 0x66, 0xc1, 0x4d, 0x2a, 0x38, - 0x7d, 0x30, 0x93, 0xd9, 0x83, 0xb9, 0x0e, 0x71, 0x89, 0xde, 0x21, 0x81, 0x95, 0x1c, 0x7a, 0x94, - 0x2b, 0x08, 0xb7, 0xa5, 0xfd, 0x5e, 0x59, 0x8f, 0xdd, 0xe6, 0x80, 0x0c, 0x73, 0xbe, 0x3f, 0xbb, - 0x15, 0x4f, 0x8a, 0x92, 0x9c, 0xeb, 0xd0, 0x26, 0xa3, 0xd8, 0xa5, 0x8e, 0xd5, 0x26, 0x81, 0xcb, - 0xb0, 0x36, 0x55, 0x51, 0x56, 0x27, 0xea, 0xcb, 0xfb, 0xbd, 0xf2, 0xb9, 0xd8, 0xd9, 0x30, 0xc2, - 0x30, 0x67, 0xe5, 0xd4, 0x27, 0x62, 0x46, 0xf5, 0x60, 0xc1, 0x77, 0xa9, 0x15, 0x10, 0x4c, 0xfc, - 0xb6, 0xd8, 0xe2, 0x00, 0x85, 0x44, 0x9b, 0x16, 0xbc, 0x3e, 0x78, 0x8e, 0xea, 0xd9, 0x26, 0xf6, - 0x93, 0x87, 0x6b, 0x90, 0xa8, 0xe4, 0x36, 0xb1, 0xcd, 0x79, 0xdf, 0xa5, 0xa6, 0xf4, 0x6b, 0xa2, - 0x90, 0x88, 0x68, 0xa8, 0x3b, 0x12, 0x6d, 0xe6, 0x3f, 0x89, 0x86, 0xba, 0x43, 0xd1, 0xde, 0x03, - 0x2d, 0x92, 0x1f, 0x4f, 0xa8, 0x89, 0x25, 0xc4, 0xdf, 0x22, 0x14, 0x35, 0x3d, 0x82, 0xb5, 0x59, - 0x21, 0x1b, 0x67, 0x3c, 0xee, 0xa7, 0xc4, 0xe6, 0x6a, 0x6c, 0xbc, 0x52, 0xf8, 0xee, 0x41, 0x79, - 0xec, 0xef, 0x07, 0xe5, 0x31, 0xe3, 0x3c, 0x2c, 0xe7, 0xd4, 0xac, 0xac, 0xe9, 0x6f, 0x15, 0x21, - 0x59, 0x5b, 0x1e, 0x72, 0xfd, 0x9b, 0x14, 0x13, 0x8f, 0x38, 0x28, 0x24, 0x58, 0xc8, 0x1a, 0x3f, - 0xe4, 0x9a, 0x56, 0xa0, 0x28, 0xaf, 0xd7, 0x40, 0x6f, 0xa0, 0x7f, 0xc3, 0x1a, 0x58, 0x5d, 0x84, - 0x93, 0xa4, 0xcd, 0xec, 0x96, 0xb8, 0x7c, 0x13, 0x66, 0x3c, 0x50, 0xcf, 0xc2, 0x24, 0x27, 0x14, - 0xcb, 0x7b, 0x97, 0x8c, 0x8c, 0x15, 0xb8, 0x70, 0x20, 0x0d, 0x49, 0x36, 0x4c, 0xae, 0x66, 0x33, - 0x16, 0x98, 0x4f, 0xfb, 0x6f, 0xe0, 0x61, 0x44, 0x33, 0x3a, 0x70, 0x62, 0x48, 0x07, 0x56, 0x60, - 0x9a, 0x76, 0x7c, 0x2b, 0xe8, 0x7b, 0x4c, 0xb8, 0x16, 0x69, 0xc7, 0x97, 0x51, 0x8c, 0x0a, 0x94, - 0xf2, 0xa3, 0xa6, 0x37, 0x71, 0x6e, 0x87, 0x3b, 0x9b, 0x18, 0xbf, 0x3c, 0xa5, 0x2b, 0x00, 0xf2, - 0x6d, 0xe7, 0xda, 0x78, 0x65, 0x7c, 0x75, 0x6a, 0x43, 0xaf, 0x0e, 0xb5, 0x0c, 0x55, 0x19, 0xc7, - 0x4c, 0xa1, 0x0d, 0x1d, 0xb4, 0x61, 0x1a, 0x92, 0xe3, 0xcf, 0x8a, 0x30, 0x46, 0xf7, 0xcf, 0x19, - 0xe4, 0x70, 0x8b, 0xb8, 0x4e, 0x2b, 0x7c, 0x51, 0xae, 0x97, 0xa0, 0xb0, 0x87, 0x3c, 0x0b, 0x61, - 0x1c, 0x24, 0xef, 0x8a, 0xf6, 0xe4, 0xe1, 0xda, 0x62, 0x52, 0xd3, 0x9b, 0x18, 0x07, 0x84, 0xf3, - 0xdd, 0x30, 0x70, 0xa9, 0x63, 0x9e, 0xda, 0x43, 0x5e, 0x34, 0x13, 0x55, 0xc0, 0x97, 0x22, 0xaa, - 0xa8, 0x80, 0x09, 0x33, 0x19, 0x19, 0x06, 0x54, 0x0e, 0xe2, 0x27, 0x93, 0xf8, 0x46, 0x01, 0x75, - 0x87, 0x3b, 0xdb, 0x24, 0x7a, 0x1d, 0x25, 0xe8, 0x55, 0xd2, 0x37, 0x5e, 0x03, 0x7d, 0x94, 0x81, - 0x24, 0xf8, 0x93, 0x92, 0x5c, 0x37, 0x1e, 0xb2, 0x80, 0x34, 0x68, 0x48, 0x02, 0xf1, 0x04, 0x6f, - 0xc6, 0xdd, 0xdc, 0x8b, 0x3d, 0xde, 0x75, 0x28, 0x26, 0xdd, 0xa0, 0x15, 0x69, 0x87, 0xe0, 0x3a, - 0xb3, 0x51, 0x1e, 0x29, 0x8a, 0xc6, 0xd6, 0x66, 0x12, 0xe7, 0xc6, 0xfd, 0x36, 0x31, 0xa7, 0xd0, - 0x60, 0x60, 0xbc, 0x01, 0x2b, 0x87, 0xf0, 0x92, 0xfc, 0xef, 0x89, 0x43, 0xb8, 0xd9, 0xc6, 0x28, - 0x95, 0xdd, 0x6e, 0x0b, 0x05, 0x84, 0x5f, 0xed, 0xda, 0x2d, 0x21, 0x4a, 0x2f, 0x94, 0x83, 0x06, - 0xd1, 0x0e, 0xb2, 0x36, 0x49, 0xb6, 0xda, 0xec, 0x0f, 0x8d, 0x8b, 0xb0, 0x7a, 0x54, 0x48, 0x49, - 0xaf, 0x23, 0xba, 0xc0, 0x81, 0x40, 0x44, 0x72, 0xf6, 0xff, 0xf7, 0x12, 0xc6, 0xb2, 0xd0, 0xc8, - 0x6c, 0xd8, 0x3e, 0xa7, 0x8d, 0x7f, 0x00, 0xc6, 0x77, 0xb8, 0xa3, 0xde, 0x82, 0xa9, 0x74, 0x6f, - 0x3a, 0x7a, 0x3c, 0xd9, 0xd6, 0x56, 0x7f, 0xeb, 0x08, 0x80, 0xec, 0x1b, 0xbf, 0x80, 0x99, 0xa1, - 0xbe, 0xd7, 0xc8, 0x5d, 0x9a, 0xc1, 0xe8, 0x17, 0x8f, 0xc6, 0xc8, 0x08, 0xb7, 0x60, 0x2a, 0xdd, - 0x9c, 0xe5, 0x52, 0x4f, 0x01, 0xf2, 0xa9, 0xe7, 0x74, 0x4c, 0xea, 0x1d, 0x98, 0x1b, 0xe9, 0x96, - 0x5e, 0xcf, 0x5f, 0x9c, 0x45, 0xe9, 0xef, 0x1e, 0x07, 0x25, 0xe3, 0x74, 0xe1, 0xec, 0x01, 0x2f, - 0x58, 0xee, 0x36, 0xe4, 0x63, 0xf5, 0x8d, 0xe3, 0x63, 0x65, 0x64, 0x06, 0x0b, 0x79, 0xef, 0xd1, - 0x01, 0x3b, 0x34, 0x02, 0xd4, 0x6b, 0xc7, 0x04, 0xca, 0x80, 0x9f, 0xc3, 0x74, 0xf6, 0x9d, 0xb9, - 0x90, 0xe7, 0x21, 0x03, 0xd1, 0xdf, 0x3e, 0x12, 0x22, 0xdd, 0x77, 0xe0, 0x4c, 0xfe, 0x13, 0x91, - 0xeb, 0x23, 0x17, 0xaa, 0xaf, 0x1f, 0x1b, 0x2a, 0xc3, 0xda, 0x30, 0x3b, 0x2c, 0xea, 0x2b, 0x79, - 0x5e, 0x86, 0x40, 0xfa, 0x3b, 0xc7, 0x00, 0xc9, 0x20, 0x5f, 0x83, 0x76, 0xa0, 0x30, 0x1f, 0x50, - 0x6f, 0xf9, 0x68, 0xfd, 0xf2, 0xf3, 0xa0, 0x65, 0xfc, 0xef, 0x15, 0x38, 0x7f, 0xb8, 0xb4, 0xe6, - 0xee, 0xdc, 0xa1, 0x4b, 0xf4, 0xf7, 0x9f, 0x7b, 0x89, 0xe4, 0x73, 0x1b, 0x8a, 0x99, 0xff, 0x2c, - 0x2b, 0xf9, 0xf5, 0x3f, 0x40, 0xe8, 0xab, 0x47, 0x21, 0xa4, 0xef, 0xcf, 0x60, 0x66, 0x48, 0xa6, - 0x73, 0x45, 0x2b, 0x8b, 0xd1, 0x8f, 0x81, 0xa9, 0x5f, 0x7b, 0xf4, 0xb4, 0xa4, 0x3c, 0x7e, 0x5a, - 0x52, 0xfe, 0x7a, 0x5a, 0x52, 0x7e, 0x78, 0x56, 0x1a, 0x7b, 0xfc, 0xac, 0x34, 0xf6, 0xc7, 0xb3, - 0xd2, 0xd8, 0xed, 0x8d, 0x94, 0xac, 0xef, 0x0a, 0x3f, 0x6b, 0xd7, 0x50, 0x93, 0xd7, 0x92, 0x6f, - 0x27, 0x7b, 0xeb, 0x97, 0x6b, 0xdd, 0xd4, 0xf7, 0x98, 0x48, 0xe6, 0x9b, 0x93, 0xe2, 0x6b, 0xc8, - 0xa5, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x9d, 0xb5, 0x94, 0xe8, 0xaf, 0x11, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcf, 0x6f, 0xdc, 0xc4, + 0x17, 0x8f, 0x9b, 0x34, 0xdd, 0xbe, 0x6c, 0x7e, 0x39, 0x69, 0xeb, 0x38, 0xdf, 0xee, 0x6e, 0x9d, + 0x2f, 0x10, 0x0a, 0xd9, 0x55, 0xd2, 0x4a, 0x88, 0x0a, 0x0e, 0xd9, 0xa4, 0x88, 0x95, 0x9a, 0x0a, + 0x39, 0x2d, 0x95, 0x2a, 0x21, 0x33, 0xeb, 0x99, 0x7a, 0xad, 0xda, 0x33, 0x5b, 0x8f, 0x37, 0x6c, + 0x39, 0x20, 0x2e, 0x48, 0x5c, 0x90, 0xe0, 0xc2, 0x11, 0xf5, 0xc0, 0x01, 0x89, 0x1b, 0xea, 0x1f, + 0xd1, 0x63, 0xd5, 0x13, 0xe2, 0xb0, 0x42, 0xed, 0x85, 0x73, 0x24, 0xee, 0xc8, 0x63, 0xef, 0xac, + 0xbd, 0xeb, 0xfc, 0x68, 0x0b, 0x39, 0x65, 0x67, 0xde, 0x67, 0xde, 0xfb, 0xbc, 0x99, 0x37, 0x9f, + 0x79, 0x31, 0x68, 0x3c, 0x0c, 0x5c, 0x4c, 0x6a, 0x3c, 0x44, 0xf7, 0x89, 0xdb, 0xb4, 0x6b, 0x61, + 0xb7, 0xda, 0x0e, 0x58, 0xc8, 0xd4, 0xd9, 0xd8, 0x52, 0xed, 0x5b, 0xf4, 0x4b, 0xc3, 0x50, 0xd7, + 0x46, 0x16, 0xb2, 0x6d, 0xd6, 0xa1, 0x61, 0xbc, 0x46, 0x2f, 0x0f, 0x43, 0xf6, 0x90, 0xe7, 0x62, + 0x14, 0xb2, 0x20, 0x01, 0x2c, 0x3a, 0xcc, 0x61, 0xe2, 0x67, 0x2d, 0xfa, 0x95, 0xcc, 0x2e, 0xd9, + 0x8c, 0xfb, 0x8c, 0x5b, 0xb1, 0x21, 0x1e, 0xc4, 0x26, 0xe3, 0x07, 0x05, 0x66, 0x76, 0xb8, 0x73, + 0xc3, 0x7d, 0xd0, 0x71, 0xf1, 0x6e, 0xe4, 0x56, 0xd5, 0xe0, 0x8c, 0x1d, 0x90, 0xc8, 0xa9, 0xa6, + 0x54, 0x94, 0xd5, 0xb3, 0x66, 0x7f, 0xa8, 0x7e, 0x04, 0x93, 0xc8, 0x8f, 0xe8, 0x68, 0xa7, 0x22, + 0x43, 0xbd, 0xfa, 0xa4, 0x57, 0x1e, 0xfb, 0xa3, 0x57, 0x7e, 0xd3, 0x71, 0xc3, 0x56, 0xa7, 0x59, + 0xb5, 0x99, 0x9f, 0x78, 0x4f, 0xfe, 0xac, 0x71, 0x7c, 0xbf, 0x16, 0x3e, 0x6c, 0x13, 0x5e, 0x6d, + 0xd0, 0xd0, 0x4c, 0x56, 0xab, 0x17, 0x01, 0x5a, 0x8c, 0x87, 0x16, 0x26, 0x94, 0xf9, 0xda, 0xb8, + 0x08, 0x72, 0x36, 0x9a, 0xd9, 0x8e, 0x26, 0x0c, 0x0d, 0xce, 0x67, 0x29, 0x99, 0x84, 0xb7, 0x19, + 0xe5, 0xc4, 0xf8, 0x59, 0x81, 0xf9, 0xc8, 0xb4, 0xbb, 0x73, 0xb2, 0x84, 0xd7, 0x60, 0xc1, 0xe3, + 0xbe, 0x15, 0xb2, 0xfb, 0x84, 0x5a, 0x6e, 0xd3, 0xce, 0x30, 0x9f, 0xf3, 0xb8, 0x7f, 0x2b, 0xb2, + 0x34, 0x9a, 0x76, 0x9c, 0xc0, 0x4d, 0x58, 0x1a, 0x61, 0xd9, 0xcf, 0x41, 0x5d, 0x87, 0xc5, 0x30, + 0x40, 0x94, 0x23, 0x3b, 0x74, 0x19, 0xb5, 0x6c, 0xe6, 0xb7, 0x3d, 0x12, 0x12, 0x41, 0xbd, 0x60, + 0x2e, 0xa4, 0x6c, 0x5b, 0x89, 0xc9, 0xf8, 0x45, 0x81, 0xd9, 0x1d, 0xee, 0x6c, 0x79, 0x04, 0x05, + 0x75, 0xe4, 0x21, 0x6a, 0x1f, 0x96, 0xf4, 0x12, 0x14, 0xec, 0x16, 0x72, 0xa9, 0xe5, 0xe2, 0x38, + 0x6d, 0xf3, 0x8c, 0x18, 0x37, 0x70, 0x6a, 0x3f, 0xc6, 0x5f, 0x6b, 0x3f, 0xa2, 0xe0, 0x2d, 0x44, + 0x29, 0xf1, 0xb4, 0x09, 0x19, 0x21, 0x1a, 0x1a, 0x4b, 0x70, 0x61, 0x88, 0xa9, 0x3c, 0xbc, 0x5f, + 0xe3, 0x52, 0x33, 0x09, 0x26, 0xc4, 0x3f, 0xa9, 0x93, 0x5b, 0x06, 0x51, 0x58, 0xd6, 0x97, 0x8c, + 0x92, 0xe4, 0xbc, 0x0a, 0xd1, 0xc4, 0x5d, 0x46, 0x89, 0xaa, 0x43, 0x21, 0x20, 0x36, 0x71, 0xf7, + 0x48, 0x90, 0xe4, 0x21, 0xc7, 0x49, 0x11, 0xa6, 0xc8, 0xca, 0x3c, 0x7e, 0x3b, 0x0d, 0x0b, 0xc2, + 0xe4, 0xb8, 0x3c, 0x24, 0xc1, 0xc7, 0x7d, 0x6f, 0x1f, 0xc2, 0xb4, 0xcd, 0x28, 0x25, 0xf1, 0xb9, + 0xf6, 0x37, 0xbf, 0xae, 0xed, 0xf7, 0xca, 0x8b, 0x0f, 0x91, 0xef, 0x5d, 0x33, 0x32, 0x66, 0xc3, + 0x2c, 0x0e, 0xc6, 0x0d, 0xac, 0x1a, 0x50, 0x6c, 0x12, 0xbb, 0x75, 0x65, 0xa3, 0x1d, 0x90, 0x7b, + 0x6e, 0x57, 0x2b, 0x0a, 0x42, 0x99, 0x39, 0xf5, 0x6a, 0xe6, 0xe2, 0x08, 0xca, 0xf5, 0x73, 0xfb, + 0xbd, 0xf2, 0x7c, 0xec, 0x7f, 0x60, 0x33, 0x52, 0xf7, 0x49, 0x5d, 0x87, 0xb3, 0x83, 0x9a, 0x3d, + 0x2d, 0x16, 0x2d, 0xee, 0xf7, 0xca, 0x73, 0xf1, 0x22, 0x69, 0x32, 0xcc, 0x82, 0x9b, 0x54, 0x70, + 0xfa, 0x60, 0x26, 0xb3, 0x07, 0x73, 0x13, 0xe2, 0x12, 0xbd, 0x47, 0x02, 0x2b, 0x39, 0xf4, 0x28, + 0x57, 0x10, 0x6e, 0x4b, 0xfb, 0xbd, 0xb2, 0x1e, 0xbb, 0xcd, 0x01, 0x19, 0xe6, 0x7c, 0x7f, 0x76, + 0x2b, 0x9e, 0x14, 0x25, 0x39, 0xd7, 0xa1, 0x4d, 0x46, 0xb1, 0x4b, 0x1d, 0xab, 0x4d, 0x02, 0x97, + 0x61, 0x6d, 0xaa, 0xa2, 0xac, 0x4e, 0xd4, 0x97, 0xf7, 0x7b, 0xe5, 0x0b, 0xb1, 0xb3, 0x61, 0x84, + 0x61, 0xce, 0xca, 0xa9, 0x4f, 0xc4, 0x8c, 0xea, 0xc1, 0x82, 0xef, 0x52, 0x2b, 0x20, 0x98, 0xf8, + 0x6d, 0xb1, 0xc5, 0x01, 0x0a, 0x89, 0x36, 0x2d, 0x78, 0x7d, 0xf0, 0x12, 0xd5, 0xb3, 0x4d, 0xec, + 0x67, 0x8f, 0xd7, 0x20, 0x51, 0xc9, 0x6d, 0x62, 0x9b, 0xf3, 0xbe, 0x4b, 0x4d, 0xe9, 0xd7, 0x44, + 0x21, 0x11, 0xd1, 0x50, 0x77, 0x24, 0xda, 0xcc, 0xbf, 0x12, 0x0d, 0x75, 0x87, 0xa2, 0xbd, 0x07, + 0x5a, 0x24, 0x3f, 0x9e, 0x50, 0x13, 0x4b, 0x88, 0xbf, 0x45, 0x28, 0x6a, 0x7a, 0x04, 0x6b, 0xb3, + 0x42, 0x36, 0xce, 0x79, 0xdc, 0x4f, 0x89, 0xcd, 0xf5, 0xd8, 0x78, 0xad, 0xf0, 0xed, 0xa3, 0xf2, + 0xd8, 0x5f, 0x8f, 0xca, 0x63, 0xc6, 0x45, 0x58, 0xce, 0xa9, 0x59, 0x59, 0xd3, 0xdf, 0x28, 0x42, + 0xb2, 0xb6, 0x3c, 0xe4, 0xfa, 0xb7, 0x29, 0x26, 0x1e, 0x71, 0x50, 0x48, 0xb0, 0x90, 0x35, 0x7e, + 0xc8, 0x35, 0xad, 0x40, 0x51, 0x5e, 0xaf, 0x81, 0xde, 0x40, 0xff, 0x86, 0x35, 0xb0, 0xba, 0x08, + 0xa7, 0x49, 0x9b, 0xd9, 0x2d, 0x71, 0xf9, 0x26, 0xcc, 0x78, 0xa0, 0x9e, 0x87, 0x49, 0x4e, 0x28, + 0x96, 0xf7, 0x2e, 0x19, 0x19, 0x2b, 0x70, 0xe9, 0x40, 0x1a, 0x92, 0x6c, 0x98, 0x5c, 0xcd, 0x66, + 0x2c, 0x30, 0x9f, 0xf6, 0xdf, 0xc0, 0xc3, 0x88, 0x66, 0x74, 0xe0, 0xd4, 0x90, 0x0e, 0xac, 0xc0, + 0x34, 0xed, 0xf8, 0x56, 0xd0, 0xf7, 0x98, 0x70, 0x2d, 0xd2, 0x8e, 0x2f, 0xa3, 0x18, 0x15, 0x28, + 0xe5, 0x47, 0x4d, 0x6f, 0xe2, 0xdc, 0x0e, 0x77, 0x36, 0x31, 0x7e, 0x7d, 0x4a, 0xd7, 0x00, 0xe4, + 0xdb, 0xce, 0xb5, 0xf1, 0xca, 0xf8, 0xea, 0xd4, 0x86, 0x5e, 0x1d, 0x6a, 0x19, 0xaa, 0x32, 0x8e, + 0x99, 0x42, 0x1b, 0x3a, 0x68, 0xc3, 0x34, 0x24, 0xc7, 0x9f, 0x14, 0x61, 0x8c, 0xee, 0x9f, 0x33, + 0xc8, 0xe1, 0x0e, 0x71, 0x9d, 0x56, 0xf8, 0xaa, 0x5c, 0xaf, 0x40, 0x61, 0x0f, 0x79, 0x16, 0xc2, + 0x38, 0x48, 0xde, 0x15, 0xed, 0xd9, 0xe3, 0xb5, 0xc5, 0xa4, 0xa6, 0x37, 0x31, 0x0e, 0x08, 0xe7, + 0xbb, 0x61, 0xe0, 0x52, 0xc7, 0x3c, 0xb3, 0x87, 0xbc, 0x68, 0x26, 0xaa, 0x80, 0x2f, 0x44, 0x54, + 0x51, 0x01, 0x13, 0x66, 0x32, 0x32, 0x0c, 0xa8, 0x1c, 0xc4, 0x4f, 0x26, 0xf1, 0xb5, 0x02, 0xea, + 0x0e, 0x77, 0xb6, 0x49, 0xf4, 0x3a, 0x4a, 0xd0, 0x49, 0xd2, 0x37, 0xfe, 0x07, 0xfa, 0x28, 0x03, + 0x49, 0xf0, 0x47, 0x25, 0xb9, 0x6e, 0x3c, 0x64, 0x01, 0x69, 0xd0, 0x90, 0x04, 0xe2, 0x09, 0xde, + 0x8c, 0xbb, 0xb9, 0x57, 0x7b, 0xbc, 0xeb, 0x50, 0x4c, 0xba, 0x41, 0x2b, 0xd2, 0x0e, 0xc1, 0x75, + 0x66, 0xa3, 0x3c, 0x52, 0x14, 0x8d, 0xad, 0xcd, 0x24, 0xce, 0xad, 0x87, 0x6d, 0x62, 0x4e, 0xa1, + 0xc1, 0xc0, 0x78, 0x03, 0x56, 0x0e, 0xe1, 0x25, 0xf9, 0x3f, 0x10, 0x87, 0x70, 0xbb, 0x8d, 0x51, + 0x2a, 0xbb, 0xdd, 0x16, 0x0a, 0x08, 0xbf, 0xde, 0xb5, 0x5b, 0x42, 0x94, 0x5e, 0x29, 0x07, 0x0d, + 0xa2, 0x1d, 0x64, 0x6d, 0x92, 0x6c, 0xb5, 0xd9, 0x1f, 0x1a, 0x97, 0x61, 0xf5, 0xa8, 0x90, 0x92, + 0x5e, 0x47, 0x74, 0x81, 0x03, 0x81, 0x88, 0xe4, 0xec, 0xbf, 0xef, 0x25, 0x8c, 0x65, 0xa1, 0x91, + 0xd9, 0xb0, 0x7d, 0x4e, 0x1b, 0x7f, 0x03, 0x8c, 0xef, 0x70, 0x47, 0xbd, 0x03, 0x53, 0xe9, 0xde, + 0x74, 0xf4, 0x78, 0xb2, 0xad, 0xad, 0xfe, 0xd6, 0x11, 0x00, 0xd9, 0x37, 0x7e, 0x0e, 0x33, 0x43, + 0x7d, 0xaf, 0x91, 0xbb, 0x34, 0x83, 0xd1, 0x2f, 0x1f, 0x8d, 0x91, 0x11, 0xee, 0xc0, 0x54, 0xba, + 0x39, 0xcb, 0xa5, 0x9e, 0x02, 0xe4, 0x53, 0xcf, 0xe9, 0x98, 0xd4, 0x7b, 0x30, 0x37, 0xd2, 0x2d, + 0xfd, 0x3f, 0x7f, 0x71, 0x16, 0xa5, 0xbf, 0x7b, 0x1c, 0x94, 0x8c, 0xd3, 0x85, 0xf3, 0x07, 0xbc, + 0x60, 0xb9, 0xdb, 0x90, 0x8f, 0xd5, 0x37, 0x8e, 0x8f, 0x95, 0x91, 0x19, 0x2c, 0xe4, 0xbd, 0x47, + 0x07, 0xec, 0xd0, 0x08, 0x50, 0xaf, 0x1d, 0x13, 0x28, 0x03, 0x7e, 0x06, 0xd3, 0xd9, 0x77, 0xe6, + 0x52, 0x9e, 0x87, 0x0c, 0x44, 0x7f, 0xfb, 0x48, 0x88, 0x74, 0xdf, 0x81, 0x73, 0xf9, 0x4f, 0x44, + 0xae, 0x8f, 0x5c, 0xa8, 0xbe, 0x7e, 0x6c, 0xa8, 0x0c, 0x6b, 0xc3, 0xec, 0xb0, 0xa8, 0xaf, 0xe4, + 0x79, 0x19, 0x02, 0xe9, 0xef, 0x1c, 0x03, 0x24, 0x83, 0x7c, 0x05, 0xda, 0x81, 0xc2, 0x7c, 0x40, + 0xbd, 0xe5, 0xa3, 0xf5, 0xab, 0x2f, 0x83, 0x96, 0xf1, 0xbf, 0x53, 0xe0, 0xe2, 0xe1, 0xd2, 0x9a, + 0xbb, 0x73, 0x87, 0x2e, 0xd1, 0xdf, 0x7f, 0xe9, 0x25, 0x92, 0xcf, 0x5d, 0x28, 0x66, 0xfe, 0xb3, + 0xac, 0xe4, 0xd7, 0xff, 0x00, 0xa1, 0xaf, 0x1e, 0x85, 0x48, 0x8b, 0xd6, 0x90, 0x4c, 0xe7, 0x8a, + 0x56, 0x16, 0x93, 0x2f, 0x5a, 0xf9, 0xba, 0x5b, 0xbf, 0xf1, 0xe4, 0x79, 0x49, 0x79, 0xfa, 0xbc, + 0xa4, 0xfc, 0xf9, 0xbc, 0xa4, 0x7c, 0xff, 0xa2, 0x34, 0xf6, 0xf4, 0x45, 0x69, 0xec, 0xf7, 0x17, + 0xa5, 0xb1, 0xbb, 0x1b, 0x29, 0x79, 0xdf, 0x15, 0xfe, 0xd6, 0x6e, 0xa0, 0x26, 0xaf, 0x25, 0xdf, + 0x50, 0xf6, 0xd6, 0xaf, 0xd6, 0xba, 0xa9, 0xef, 0x32, 0x91, 0xdc, 0x37, 0x27, 0xc5, 0x57, 0x91, + 0x2b, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8f, 0x86, 0x99, 0x50, 0xb7, 0x11, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1409,7 +1409,7 @@ type MsgClient interface { RestoreInterchainAccount(ctx context.Context, in *MsgRestoreInterchainAccount, opts ...grpc.CallOption) (*MsgRestoreInterchainAccountResponse, error) UpdateValidatorSharesExchRate(ctx context.Context, in *MsgUpdateValidatorSharesExchRate, opts ...grpc.CallOption) (*MsgUpdateValidatorSharesExchRateResponse, error) ClearBalance(ctx context.Context, in *MsgClearBalance, opts ...grpc.CallOption) (*MsgClearBalanceResponse, error) - UndelegateHost(ctx context.Context, in *MsgUndelegateHost, opts ...grpc.CallOption) (*MsgUndelegateHost, error) + UndelegateHost(ctx context.Context, in *MsgUndelegateHost, opts ...grpc.CallOption) (*MsgUndelegateHostResponse, error) } type msgClient struct { @@ -1528,8 +1528,8 @@ func (c *msgClient) ClearBalance(ctx context.Context, in *MsgClearBalance, opts return out, nil } -func (c *msgClient) UndelegateHost(ctx context.Context, in *MsgUndelegateHost, opts ...grpc.CallOption) (*MsgUndelegateHost, error) { - out := new(MsgUndelegateHost) +func (c *msgClient) UndelegateHost(ctx context.Context, in *MsgUndelegateHost, opts ...grpc.CallOption) (*MsgUndelegateHostResponse, error) { + out := new(MsgUndelegateHostResponse) err := c.cc.Invoke(ctx, "/stride.stakeibc.Msg/UndelegateHost", in, out, opts...) if err != nil { return nil, err @@ -1551,7 +1551,7 @@ type MsgServer interface { RestoreInterchainAccount(context.Context, *MsgRestoreInterchainAccount) (*MsgRestoreInterchainAccountResponse, error) UpdateValidatorSharesExchRate(context.Context, *MsgUpdateValidatorSharesExchRate) (*MsgUpdateValidatorSharesExchRateResponse, error) ClearBalance(context.Context, *MsgClearBalance) (*MsgClearBalanceResponse, error) - UndelegateHost(context.Context, *MsgUndelegateHost) (*MsgUndelegateHost, error) + UndelegateHost(context.Context, *MsgUndelegateHost) (*MsgUndelegateHostResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -1594,7 +1594,7 @@ func (*UnimplementedMsgServer) UpdateValidatorSharesExchRate(ctx context.Context func (*UnimplementedMsgServer) ClearBalance(ctx context.Context, req *MsgClearBalance) (*MsgClearBalanceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ClearBalance not implemented") } -func (*UnimplementedMsgServer) UndelegateHost(ctx context.Context, req *MsgUndelegateHost) (*MsgUndelegateHost, error) { +func (*UnimplementedMsgServer) UndelegateHost(ctx context.Context, req *MsgUndelegateHost) (*MsgUndelegateHostResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UndelegateHost not implemented") } From fd7732d53259323945112025dfb2d74bab90ae02 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sat, 16 Sep 2023 21:47:21 -0400 Subject: [PATCH 04/27] undelegatehost outline + copy of UnbondFromHostZone as UndelegateHostEvmos --- x/stakeibc/keeper/msg_undelegate_host.go | 15 +++++++++++++++ x/stakeibc/types/errors.go | 1 + x/stakeibc/types/message_undelegate_host.go | 3 +++ 3 files changed, 19 insertions(+) diff --git a/x/stakeibc/keeper/msg_undelegate_host.go b/x/stakeibc/keeper/msg_undelegate_host.go index ac1988df61..39d93f3664 100644 --- a/x/stakeibc/keeper/msg_undelegate_host.go +++ b/x/stakeibc/keeper/msg_undelegate_host.go @@ -4,14 +4,29 @@ import ( "context" "fmt" + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/Stride-Labs/stride/v14/x/stakeibc/types" ) +const ( + isCallable = true +) + func (k msgServer) UndelegateHost(goCtx context.Context, msg *types.MsgUndelegateHost) (*types.MsgUndelegateHostResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) + // undelegateHost is callable only if it has not yet been called and succeeded + if !isCallable { + return nil, errorsmod.Wrapf(types.ErrUndelegateHostNotCallable, "") + } + + // Get host zone unbonding message by summing up the unbonding records + if err := k.UndelegateHostEvmos(ctx, msg.Amount); err != nil { + k.Logger(ctx).Error(fmt.Sprintf("Error initiating host zone unbondings for UndelegateHostEvmos", err.Error())) + } + // log: issuing an undelegation to Evmos k.Logger(ctx).Info(fmt.Sprintf("Issuing an undelegation to Evmos")) diff --git a/x/stakeibc/types/errors.go b/x/stakeibc/types/errors.go index bf9f815aee..57a56148f3 100644 --- a/x/stakeibc/types/errors.go +++ b/x/stakeibc/types/errors.go @@ -56,4 +56,5 @@ var ( ErrInvalidValidatorDelegationUpdates = errorsmod.Register(ModuleName, 1548, "Invalid validator delegation updates") ErrLSMLiquidStakeDisabledForHostZone = errorsmod.Register(ModuleName, 1549, "LSM liquid stake is disabled for host zone") ErrUnableToRemoveValidator = errorsmod.Register(ModuleName, 1550, "Unable to remove validator") + ErrUndelegateHostNotCallable = errorsmod.Register(ModuleName, 1551, "Unable to call undelegate host") ) diff --git a/x/stakeibc/types/message_undelegate_host.go b/x/stakeibc/types/message_undelegate_host.go index 3a045e28b5..d239604cf8 100644 --- a/x/stakeibc/types/message_undelegate_host.go +++ b/x/stakeibc/types/message_undelegate_host.go @@ -49,5 +49,8 @@ func (msg *MsgUndelegateHost) ValidateBasic() error { if err := utils.ValidateAdminAddress(msg.Creator); err != nil { return err } + if msg.Amount.IsZero() { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "amount must be positive") + } return nil } From 0b37cd5328f4a3ccb5561d9242d3a15bb0c888ff Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sat, 16 Sep 2023 21:48:09 -0400 Subject: [PATCH 05/27] write undelegateHostEvmos --- x/stakeibc/keeper/undelegate_host.go | 134 +++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 x/stakeibc/keeper/undelegate_host.go diff --git a/x/stakeibc/keeper/undelegate_host.go b/x/stakeibc/keeper/undelegate_host.go new file mode 100644 index 0000000000..ff60df92e6 --- /dev/null +++ b/x/stakeibc/keeper/undelegate_host.go @@ -0,0 +1,134 @@ +package keeper + +import ( + "fmt" + + errorsmod "cosmossdk.io/errors" + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/gogoproto/proto" + + "github.com/Stride-Labs/stride/v14/utils" + "github.com/Stride-Labs/stride/v14/x/stakeibc/types" +) + +const ( + MaxNumTokensUnbondable = 1000000000000000000 // 1e18 + EvmosHostZoneChainId = "evmos-9001_2" // TODO: remove this hardcoded value +) + +// Submits undelegation ICA message for Evmos +// The total unbond amount is input, capped at MaxNumTokensUnbondable. +func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) error { + + // Get the host zone + evmosHost, found := k.GetHostZone(ctx, EvmosHostZoneChainId) + if !found { + return errorsmod.Wrapf(types.ErrHostZoneNotFound, "host zone %s not found", EvmosHostZoneChainId) + } + + k.Logger(ctx).Info(utils.LogWithHostZone(evmosHost.ChainId, + "Total unbonded amount: %v%s", totalUnbondAmount, evmosHost.HostDenom)) + + // If there's nothing to unbond, return and move on to the next host zone + if totalUnbondAmount.IsZero() { + return nil + } + + // if the total unbond amount is greater than the max, exit + // TODO: this overflows above ~100e18, NEED NEW TYPE + if totalUnbondAmount.GT(math.NewInt(MaxNumTokensUnbondable)) { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "total unbond amount %v%s is greater than MaxNumTokensUnbondable %v%s", + totalUnbondAmount, evmosHost.HostDenom, MaxNumTokensUnbondable, evmosHost.HostDenom) + } + + k.Logger(ctx).Info("Preparing MsgUndelegates from the delegation account to each validator on Evmos") + + // Confirm the delegation account was registered + if evmosHost.DelegationIcaAddress == "" { + return errorsmod.Wrapf(types.ErrICAAccountNotFound, "no delegation account found for %s", evmosHost.ChainId) + } + + // Determine the ideal balanced delegation for each validator after the unbonding + // (as if we were to unbond and then rebalance) + // This will serve as the starting point for determining how much to unbond each validator + delegationAfterUnbonding := evmosHost.TotalDelegations.Sub(totalUnbondAmount) + balancedDelegationsAfterUnbonding, err := k.GetTargetValAmtsForHostZone(ctx, evmosHost, delegationAfterUnbonding) + if err != nil { + return errorsmod.Wrapf(err, "unable to get target val amounts for host zone %s", evmosHost.ChainId) + } + + // Determine the unbond capacity for each validator + // Each validator can only unbond up to the difference between their current delegation and their balanced delegation + // The validator's current delegation will be above their balanced delegation if they've received LSM Liquid Stakes + // (which is only rebalanced once per unbonding period) + validatorUnbondCapacity := k.GetValidatorUnbondCapacity(ctx, evmosHost.Validators, balancedDelegationsAfterUnbonding) + if len(validatorUnbondCapacity) == 0 { + return fmt.Errorf("there are no validators on %s with sufficient unbond capacity", evmosHost.ChainId) + } + + // Sort the unbonding capacity by priority + // Priority is determined by checking the how proportionally unbalanced each validator is + // Zero weight validators will come first in the list + prioritizedUnbondCapacity, err := SortUnbondingCapacityByPriority(validatorUnbondCapacity) + if err != nil { + return err + } + + // Get the undelegation ICA messages and split delegations for the callback + msgs, unbondings, err := k.GetUnbondingICAMessages(evmosHost, totalUnbondAmount, prioritizedUnbondCapacity) + if err != nil { + return err + } + + // Shouldn't be possible, but if all the validator's had a target unbonding of zero, do not send an ICA + if len(msgs) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Target unbonded amount was 0 for each validator") + } + + // Send the messages in batches so the gas limit isn't exceedeed + for start := 0; start < len(msgs); start += UndelegateICABatchSize { + end := start + UndelegateICABatchSize + if end > len(msgs) { + end = len(msgs) + } + + msgsBatch := msgs[start:end] + unbondingsBatch := unbondings[start:end] + + // Store the callback data + undelegateCallback := types.UndelegateCallback{ + HostZoneId: evmosHost.ChainId, + SplitDelegations: unbondingsBatch, + } + callbackArgsBz, err := proto.Marshal(&undelegateCallback) + if err != nil { + return errorsmod.Wrap(err, "unable to marshal undelegate callback args") + } + + // Submit the undelegation ICA + if _, err := k.SubmitTxsDayEpoch( + ctx, + evmosHost.ConnectionId, + msgsBatch, + types.ICAAccountType_DELEGATION, + ICACallbackID_Undelegate, + callbackArgsBz, + ); err != nil { + return errorsmod.Wrapf(err, "unable to submit unbonding ICA for %s", evmosHost.ChainId) + } + + // flag the delegation change in progress on each validator + for _, unbonding := range unbondingsBatch { + if err := k.IncrementValidatorDelegationChangesInProgress(&evmosHost, unbonding.Validator); err != nil { + return err + } + } + k.SetHostZone(ctx, evmosHost) + } + + EmitUndelegationEvent(ctx, evmosHost, totalUnbondAmount) + + return nil +} From a4c082da7753454e2452436ba116c8d099368150 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sat, 16 Sep 2023 22:16:33 -0400 Subject: [PATCH 06/27] clone undelegate callback --- x/stakeibc/keeper/icacallbacks.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/x/stakeibc/keeper/icacallbacks.go b/x/stakeibc/keeper/icacallbacks.go index a338245cc5..a611929806 100644 --- a/x/stakeibc/keeper/icacallbacks.go +++ b/x/stakeibc/keeper/icacallbacks.go @@ -5,13 +5,14 @@ import ( ) const ( - ICACallbackID_Delegate = "delegate" - ICACallbackID_Claim = "claim" - ICACallbackID_Undelegate = "undelegate" - ICACallbackID_Reinvest = "reinvest" - ICACallbackID_Redemption = "redemption" - ICACallbackID_Rebalance = "rebalance" - ICACallbackID_Detokenize = "detokenize" + ICACallbackID_Delegate = "delegate" + ICACallbackID_Claim = "claim" + ICACallbackID_Undelegate = "undelegate" + ICACallbackID_UndelegateHost = "undelegatehost" + ICACallbackID_Reinvest = "reinvest" + ICACallbackID_Redemption = "redemption" + ICACallbackID_Rebalance = "rebalance" + ICACallbackID_Detokenize = "detokenize" ) func (k Keeper) Callbacks() icacallbackstypes.ModuleCallbacks { @@ -19,6 +20,7 @@ func (k Keeper) Callbacks() icacallbackstypes.ModuleCallbacks { {CallbackId: ICACallbackID_Delegate, CallbackFunc: icacallbackstypes.ICACallbackFunction(k.DelegateCallback)}, {CallbackId: ICACallbackID_Claim, CallbackFunc: icacallbackstypes.ICACallbackFunction(k.ClaimCallback)}, {CallbackId: ICACallbackID_Undelegate, CallbackFunc: icacallbackstypes.ICACallbackFunction(k.UndelegateCallback)}, + {CallbackId: ICACallbackID_UndelegateHost, CallbackFunc: icacallbackstypes.ICACallbackFunction(k.UndelegateHostCallback)}, {CallbackId: ICACallbackID_Reinvest, CallbackFunc: icacallbackstypes.ICACallbackFunction(k.ReinvestCallback)}, {CallbackId: ICACallbackID_Redemption, CallbackFunc: icacallbackstypes.ICACallbackFunction(k.RedemptionCallback)}, {CallbackId: ICACallbackID_Rebalance, CallbackFunc: icacallbackstypes.ICACallbackFunction(k.RebalanceCallback)}, From 6d87e5f81e397c00fa807c1e6d7672afd18a64f5 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sat, 16 Sep 2023 22:50:20 -0400 Subject: [PATCH 07/27] undelegate host --- proto/stride/stakeibc/callbacks.proto | 7 + x/stakeibc/keeper/icacallbacks_undelegate.go | 37 +++ x/stakeibc/keeper/undelegate_host.go | 13 +- x/stakeibc/types/callbacks.pb.go | 287 +++++++++++++++---- 4 files changed, 277 insertions(+), 67 deletions(-) diff --git a/proto/stride/stakeibc/callbacks.proto b/proto/stride/stakeibc/callbacks.proto index 11738336df..e0ecb6f9ea 100644 --- a/proto/stride/stakeibc/callbacks.proto +++ b/proto/stride/stakeibc/callbacks.proto @@ -42,6 +42,13 @@ message UndelegateCallback { repeated uint64 epoch_unbonding_record_ids = 3; } +message UndelegateHostCallback { + string amt = 1 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; +} + message RedemptionCallback { string host_zone_id = 1; repeated uint64 epoch_unbonding_record_ids = 2; diff --git a/x/stakeibc/keeper/icacallbacks_undelegate.go b/x/stakeibc/keeper/icacallbacks_undelegate.go index 76e05938b1..a8f3965030 100644 --- a/x/stakeibc/keeper/icacallbacks_undelegate.go +++ b/x/stakeibc/keeper/icacallbacks_undelegate.go @@ -233,3 +233,40 @@ func (k Keeper) BurnTokens(ctx sdk.Context, hostZone types.HostZone, stTokenBurn k.Logger(ctx).Info(fmt.Sprintf("Total supply %s", k.bankKeeper.GetSupply(ctx, stCoinDenom))) return nil } + +// ICA Callback after undelegating host +// +// If successful: +// * sets isCallable = false +// If timeout: +// * Does nothing +// If failure: +// * Does nothing +func (k Keeper) UndelegateHostCallback(ctx sdk.Context, packet channeltypes.Packet, ackResponse *icacallbackstypes.AcknowledgementResponse, args []byte) error { + // Fetch callback args + var undelegateHostCallback types.UndelegateHostCallback + if err := proto.Unmarshal(args, &undelegateHostCallback); err != nil { + return errorsmod.Wrapf(types.ErrUnmarshalFailure, fmt.Sprintf("Unable to unmarshal undelegate host callback args: %s", err.Error())) + } + k.Logger(ctx).Info("Starting undelegate host callback for amount %v%s", undelegateHostCallback.Amt) + + // Check for timeout (ack nil) + if ackResponse.Status == icacallbackstypes.AckResponseStatus_TIMEOUT { + k.Logger(ctx).Error("UndelegateHostCallback Timeout:", icacallbackstypes.AckResponseStatus_TIMEOUT, packet) + return nil + } + + // Check for a failed transaction (ack error) + if ackResponse.Status == icacallbackstypes.AckResponseStatus_FAILURE { + k.Logger(ctx).Error("UndelegateHostCallback failure (ack error):", icacallbackstypes.AckResponseStatus_FAILURE, packet) + return nil + } + + k.Logger(ctx).Info("UndelegateHostCallback success:", icacallbackstypes.AckResponseStatus_SUCCESS, packet) + + // TODO set isCallable = false + // log "isCallable has been set to false" + k.Logger(ctx).Info(">>>>>>>>>>> isCallable has been set to false. <<<<<<<<<<<<<<<") + + return nil +} diff --git a/x/stakeibc/keeper/undelegate_host.go b/x/stakeibc/keeper/undelegate_host.go index ff60df92e6..8dd06b561b 100644 --- a/x/stakeibc/keeper/undelegate_host.go +++ b/x/stakeibc/keeper/undelegate_host.go @@ -15,7 +15,7 @@ import ( const ( MaxNumTokensUnbondable = 1000000000000000000 // 1e18 - EvmosHostZoneChainId = "evmos-9001_2" // TODO: remove this hardcoded value + EvmosHostZoneChainId = "GAIA" // "evmos-9001_2" // TODO: set value to "evmos-9001_2", remove this hardcoded value ) // Submits undelegation ICA message for Evmos @@ -98,13 +98,12 @@ func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) unbondingsBatch := unbondings[start:end] // Store the callback data - undelegateCallback := types.UndelegateCallback{ - HostZoneId: evmosHost.ChainId, - SplitDelegations: unbondingsBatch, + undelegateHostCallback := types.UndelegateHostCallback{ + Amt: totalUnbondAmount, } - callbackArgsBz, err := proto.Marshal(&undelegateCallback) + callbackArgsBz, err := proto.Marshal(&undelegateHostCallback) if err != nil { - return errorsmod.Wrap(err, "unable to marshal undelegate callback args") + return errorsmod.Wrap(err, "unable to marshal undelegate host callback args") } // Submit the undelegation ICA @@ -113,7 +112,7 @@ func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) evmosHost.ConnectionId, msgsBatch, types.ICAAccountType_DELEGATION, - ICACallbackID_Undelegate, + ICACallbackID_UndelegateHost, callbackArgsBz, ); err != nil { return errorsmod.Wrapf(err, "unable to submit unbonding ICA for %s", evmosHost.ChainId) diff --git a/x/stakeibc/types/callbacks.pb.go b/x/stakeibc/types/callbacks.pb.go index fd9999cd38..1f7caa8af7 100644 --- a/x/stakeibc/types/callbacks.pb.go +++ b/x/stakeibc/types/callbacks.pb.go @@ -303,6 +303,43 @@ func (m *UndelegateCallback) GetEpochUnbondingRecordIds() []uint64 { return nil } +type UndelegateHostCallback struct { + Amt github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,1,opt,name=amt,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"amt"` +} + +func (m *UndelegateHostCallback) Reset() { *m = UndelegateHostCallback{} } +func (m *UndelegateHostCallback) String() string { return proto.CompactTextString(m) } +func (*UndelegateHostCallback) ProtoMessage() {} +func (*UndelegateHostCallback) Descriptor() ([]byte, []int) { + return fileDescriptor_f41c99b09b96a5ac, []int{5} +} +func (m *UndelegateHostCallback) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *UndelegateHostCallback) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_UndelegateHostCallback.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 *UndelegateHostCallback) XXX_Merge(src proto.Message) { + xxx_messageInfo_UndelegateHostCallback.Merge(m, src) +} +func (m *UndelegateHostCallback) XXX_Size() int { + return m.Size() +} +func (m *UndelegateHostCallback) XXX_DiscardUnknown() { + xxx_messageInfo_UndelegateHostCallback.DiscardUnknown(m) +} + +var xxx_messageInfo_UndelegateHostCallback proto.InternalMessageInfo + type RedemptionCallback struct { HostZoneId string `protobuf:"bytes,1,opt,name=host_zone_id,json=hostZoneId,proto3" json:"host_zone_id,omitempty"` EpochUnbondingRecordIds []uint64 `protobuf:"varint,2,rep,packed,name=epoch_unbonding_record_ids,json=epochUnbondingRecordIds,proto3" json:"epoch_unbonding_record_ids,omitempty"` @@ -312,7 +349,7 @@ func (m *RedemptionCallback) Reset() { *m = RedemptionCallback{} } func (m *RedemptionCallback) String() string { return proto.CompactTextString(m) } func (*RedemptionCallback) ProtoMessage() {} func (*RedemptionCallback) Descriptor() ([]byte, []int) { - return fileDescriptor_f41c99b09b96a5ac, []int{5} + return fileDescriptor_f41c99b09b96a5ac, []int{6} } func (m *RedemptionCallback) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -365,7 +402,7 @@ func (m *Rebalancing) Reset() { *m = Rebalancing{} } func (m *Rebalancing) String() string { return proto.CompactTextString(m) } func (*Rebalancing) ProtoMessage() {} func (*Rebalancing) Descriptor() ([]byte, []int) { - return fileDescriptor_f41c99b09b96a5ac, []int{6} + return fileDescriptor_f41c99b09b96a5ac, []int{7} } func (m *Rebalancing) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -417,7 +454,7 @@ func (m *RebalanceCallback) Reset() { *m = RebalanceCallback{} } func (m *RebalanceCallback) String() string { return proto.CompactTextString(m) } func (*RebalanceCallback) ProtoMessage() {} func (*RebalanceCallback) Descriptor() ([]byte, []int) { - return fileDescriptor_f41c99b09b96a5ac, []int{7} + return fileDescriptor_f41c99b09b96a5ac, []int{8} } func (m *RebalanceCallback) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -468,7 +505,7 @@ func (m *DetokenizeSharesCallback) Reset() { *m = DetokenizeSharesCallba func (m *DetokenizeSharesCallback) String() string { return proto.CompactTextString(m) } func (*DetokenizeSharesCallback) ProtoMessage() {} func (*DetokenizeSharesCallback) Descriptor() ([]byte, []int) { - return fileDescriptor_f41c99b09b96a5ac, []int{8} + return fileDescriptor_f41c99b09b96a5ac, []int{9} } func (m *DetokenizeSharesCallback) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -514,7 +551,7 @@ func (m *LSMLiquidStake) Reset() { *m = LSMLiquidStake{} } func (m *LSMLiquidStake) String() string { return proto.CompactTextString(m) } func (*LSMLiquidStake) ProtoMessage() {} func (*LSMLiquidStake) Descriptor() ([]byte, []int) { - return fileDescriptor_f41c99b09b96a5ac, []int{9} + return fileDescriptor_f41c99b09b96a5ac, []int{10} } func (m *LSMLiquidStake) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -572,7 +609,7 @@ func (m *ValidatorSharesToTokensQueryCallback) Reset() { *m = ValidatorS func (m *ValidatorSharesToTokensQueryCallback) String() string { return proto.CompactTextString(m) } func (*ValidatorSharesToTokensQueryCallback) ProtoMessage() {} func (*ValidatorSharesToTokensQueryCallback) Descriptor() ([]byte, []int) { - return fileDescriptor_f41c99b09b96a5ac, []int{10} + return fileDescriptor_f41c99b09b96a5ac, []int{11} } func (m *ValidatorSharesToTokensQueryCallback) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -617,7 +654,7 @@ func (m *DelegatorSharesQueryCallback) Reset() { *m = DelegatorSharesQue func (m *DelegatorSharesQueryCallback) String() string { return proto.CompactTextString(m) } func (*DelegatorSharesQueryCallback) ProtoMessage() {} func (*DelegatorSharesQueryCallback) Descriptor() ([]byte, []int) { - return fileDescriptor_f41c99b09b96a5ac, []int{11} + return fileDescriptor_f41c99b09b96a5ac, []int{12} } func (m *DelegatorSharesQueryCallback) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -652,6 +689,7 @@ func init() { proto.RegisterType((*ClaimCallback)(nil), "stride.stakeibc.ClaimCallback") proto.RegisterType((*ReinvestCallback)(nil), "stride.stakeibc.ReinvestCallback") proto.RegisterType((*UndelegateCallback)(nil), "stride.stakeibc.UndelegateCallback") + proto.RegisterType((*UndelegateHostCallback)(nil), "stride.stakeibc.UndelegateHostCallback") proto.RegisterType((*RedemptionCallback)(nil), "stride.stakeibc.RedemptionCallback") proto.RegisterType((*Rebalancing)(nil), "stride.stakeibc.Rebalancing") proto.RegisterType((*RebalanceCallback)(nil), "stride.stakeibc.RebalanceCallback") @@ -664,59 +702,60 @@ func init() { func init() { proto.RegisterFile("stride/stakeibc/callbacks.proto", fileDescriptor_f41c99b09b96a5ac) } var fileDescriptor_f41c99b09b96a5ac = []byte{ - // 822 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x4f, 0x6f, 0xeb, 0x44, - 0x10, 0x8f, 0x9b, 0xa7, 0xf7, 0x5e, 0x36, 0x69, 0x93, 0x5a, 0x08, 0xd2, 0x28, 0x4a, 0x82, 0x1f, - 0x82, 0x0a, 0xa9, 0xb6, 0x5a, 0x10, 0x02, 0x71, 0x29, 0x6d, 0x85, 0x88, 0x94, 0x22, 0xe1, 0xb4, - 0x1c, 0x7a, 0xb1, 0xd6, 0xde, 0x55, 0xb2, 0x8a, 0xbd, 0x9b, 0x7a, 0x37, 0x29, 0xed, 0x27, 0xe0, - 0xd8, 0x2b, 0x1f, 0x01, 0x2e, 0x7c, 0x02, 0x2e, 0x9c, 0x7a, 0xec, 0x11, 0x71, 0x28, 0xa8, 0xfd, - 0x22, 0x68, 0xd7, 0xeb, 0x3f, 0x49, 0xa0, 0x22, 0x70, 0x4a, 0x3c, 0xf3, 0x9b, 0x9d, 0xf9, 0xcd, - 0x6f, 0x66, 0x17, 0x74, 0xb9, 0x88, 0x09, 0xc2, 0x0e, 0x17, 0x70, 0x82, 0x89, 0x1f, 0x38, 0x01, - 0x0c, 0x43, 0x1f, 0x06, 0x13, 0x6e, 0x4f, 0x63, 0x26, 0x98, 0x59, 0x4f, 0x00, 0x76, 0x0a, 0x68, - 0xbd, 0x35, 0x62, 0x23, 0xa6, 0x7c, 0x8e, 0xfc, 0x97, 0xc0, 0x5a, 0x9d, 0x80, 0xf1, 0x88, 0x71, - 0xc7, 0x87, 0x1c, 0x3b, 0xf3, 0x7d, 0x1f, 0x0b, 0xb8, 0xef, 0x04, 0x8c, 0x50, 0xed, 0x6f, 0xeb, - 0x3c, 0x31, 0x0e, 0x58, 0x8c, 0x78, 0xfa, 0xab, 0xbd, 0x2b, 0x55, 0x8c, 0x19, 0x17, 0xde, 0x0d, - 0xa3, 0xf8, 0x9f, 0x00, 0x73, 0x18, 0x12, 0x04, 0x05, 0x8b, 0x13, 0x80, 0x75, 0x05, 0xea, 0xc3, - 0x69, 0x48, 0xc4, 0x09, 0x0e, 0xf1, 0x08, 0x0a, 0xc2, 0xa8, 0xd9, 0x06, 0x95, 0x0c, 0xd5, 0x34, - 0x7a, 0xc6, 0x6e, 0xc5, 0xcd, 0x0d, 0xe6, 0x97, 0xe0, 0x25, 0x8c, 0xd8, 0x8c, 0x8a, 0xe6, 0x86, - 0x74, 0x1d, 0xd9, 0x77, 0x0f, 0xdd, 0xd2, 0xef, 0x0f, 0xdd, 0xf7, 0x47, 0x44, 0x8c, 0x67, 0xbe, - 0x1d, 0xb0, 0xc8, 0xd1, 0x9c, 0x92, 0x9f, 0x3d, 0x8e, 0x26, 0x8e, 0xb8, 0x9e, 0x62, 0x6e, 0xf7, - 0xa9, 0x70, 0x75, 0xb4, 0xf5, 0xb3, 0x01, 0x1a, 0x3a, 0x29, 0x3e, 0xd6, 0xbd, 0x33, 0x7b, 0xa0, - 0x96, 0x31, 0xf0, 0x08, 0xd2, 0xd9, 0x81, 0xb4, 0x5d, 0x30, 0x8a, 0xfb, 0xc8, 0xfc, 0x10, 0x6c, - 0x23, 0x3c, 0x65, 0x9c, 0x08, 0x2f, 0x69, 0x85, 0x84, 0xc9, 0x4a, 0x5e, 0xb8, 0x75, 0xed, 0x70, - 0x95, 0xbd, 0x8f, 0xcc, 0x53, 0xb0, 0xcd, 0x25, 0x37, 0x0f, 0x65, 0xe4, 0x78, 0xb3, 0xdc, 0x2b, - 0xef, 0x56, 0x0f, 0x7a, 0xf6, 0x92, 0x3c, 0xf6, 0x52, 0x17, 0xdc, 0x06, 0x5f, 0x34, 0x70, 0xeb, - 0x7b, 0x03, 0x6c, 0x1e, 0x87, 0x90, 0x44, 0x59, 0xb9, 0x9f, 0x81, 0x9d, 0x19, 0xc7, 0xb1, 0x17, - 0x63, 0x84, 0xa3, 0xa9, 0x44, 0x15, 0x8a, 0x4a, 0x6a, 0x7f, 0x5b, 0x02, 0xdc, 0xcc, 0x9f, 0xd5, - 0xb6, 0x03, 0x5e, 0x07, 0x63, 0x48, 0x68, 0x5a, 0x7e, 0xc5, 0x7d, 0xa5, 0xbe, 0xfb, 0xc8, 0x7c, - 0x17, 0xd4, 0xf0, 0x94, 0x05, 0x63, 0x8f, 0xce, 0x22, 0x1f, 0xc7, 0xcd, 0xb2, 0x62, 0x57, 0x55, - 0xb6, 0xaf, 0x95, 0xc9, 0xfa, 0xd1, 0x00, 0x0d, 0x17, 0x13, 0x3a, 0xc7, 0x5c, 0x64, 0xd5, 0x70, - 0x50, 0x8f, 0xb5, 0xcd, 0xd3, 0x12, 0xc9, 0x1a, 0xaa, 0x07, 0x3b, 0x76, 0xa2, 0x84, 0x2d, 0x87, - 0xcc, 0xd6, 0x43, 0x66, 0x1f, 0x33, 0x42, 0x8f, 0x1c, 0xa9, 0xde, 0x4f, 0x7f, 0x74, 0x3f, 0xf8, - 0x17, 0xea, 0xc9, 0x00, 0x77, 0x2b, 0x4d, 0xf1, 0x85, 0xca, 0xb0, 0xa2, 0x58, 0x79, 0x59, 0x31, - 0xeb, 0x57, 0x03, 0x98, 0xe7, 0x14, 0xad, 0x2f, 0xf5, 0xdf, 0xca, 0xb7, 0xf1, 0x5f, 0xe5, 0x33, - 0x3f, 0x07, 0xad, 0xa4, 0xad, 0x33, 0xea, 0x33, 0x8a, 0x08, 0x1d, 0xe5, 0x62, 0x25, 0x63, 0xf1, - 0xc2, 0x7d, 0x47, 0x21, 0xce, 0x53, 0x40, 0xaa, 0x16, 0xb7, 0x38, 0x30, 0x73, 0x11, 0xd7, 0xe0, - 0xf0, 0x7c, 0xd2, 0x8d, 0xe7, 0x93, 0xfe, 0x60, 0x80, 0xaa, 0x8b, 0x7d, 0x18, 0x42, 0x1a, 0x10, - 0x3a, 0x32, 0xdf, 0x80, 0x4d, 0x1e, 0x07, 0xde, 0xf2, 0x72, 0xd6, 0x78, 0x1c, 0x7c, 0x9b, 0xed, - 0xe7, 0x1b, 0xb0, 0x89, 0xb8, 0x28, 0x80, 0x92, 0xe9, 0xaa, 0x21, 0x2e, 0x72, 0xd0, 0x21, 0x28, - 0xc3, 0x48, 0x24, 0x62, 0xad, 0xbd, 0xc1, 0x32, 0xd4, 0xba, 0x02, 0xdb, 0x69, 0x69, 0xeb, 0x68, - 0x7a, 0x08, 0x6a, 0x71, 0xce, 0x28, 0x95, 0xb3, 0xbd, 0x22, 0x67, 0x81, 0xb6, 0xbb, 0x10, 0x61, - 0x9d, 0x83, 0xe6, 0x09, 0x16, 0x6c, 0x82, 0x29, 0xb9, 0xc1, 0xc3, 0x31, 0x8c, 0x31, 0x2f, 0xec, - 0xe3, 0x2b, 0x7d, 0x07, 0xe8, 0xc9, 0xef, 0xa6, 0x07, 0xa7, 0xd7, 0xe6, 0x60, 0x78, 0x7a, 0x26, - 0x63, 0x4f, 0xf4, 0x55, 0x91, 0xe2, 0xad, 0x5f, 0x0c, 0xb0, 0x35, 0x18, 0x9e, 0x0e, 0xc8, 0xe5, - 0x8c, 0xa0, 0xa1, 0x2c, 0xe3, 0x7f, 0x9c, 0x66, 0x7e, 0x02, 0x2a, 0x59, 0x23, 0x94, 0x00, 0x72, - 0x09, 0x97, 0x39, 0x7e, 0xa5, 0xdb, 0xe2, 0xbe, 0x4e, 0x1b, 0x64, 0x7e, 0x5a, 0xbc, 0x7a, 0xcb, - 0x2a, 0xae, 0xb5, 0x12, 0x97, 0xc9, 0x58, 0xb8, 0x96, 0xad, 0x4b, 0xf0, 0x5e, 0x66, 0x4f, 0xba, - 0x72, 0xc6, 0x54, 0x6d, 0xfc, 0x9b, 0x19, 0x8e, 0xaf, 0xb3, 0x16, 0xf5, 0x41, 0x23, 0xe4, 0x91, - 0x17, 0x2a, 0x9e, 0x9e, 0x3a, 0x73, 0x99, 0x5d, 0x96, 0x68, 0xb1, 0x1f, 0xee, 0x56, 0xc8, 0xa3, - 0xc2, 0xb7, 0x75, 0x6b, 0x80, 0xb6, 0x5e, 0xb0, 0x34, 0xe7, 0x62, 0xae, 0x29, 0x68, 0x13, 0x4a, - 0x04, 0x81, 0x61, 0x3e, 0x8e, 0x85, 0x65, 0x4e, 0xc6, 0x63, 0xed, 0xf1, 0x6b, 0xe9, 0x33, 0x33, - 0xba, 0xf9, 0x92, 0x1f, 0x0d, 0xee, 0x1e, 0x3b, 0xc6, 0xfd, 0x63, 0xc7, 0xf8, 0xf3, 0xb1, 0x63, - 0xdc, 0x3e, 0x75, 0x4a, 0xf7, 0x4f, 0x9d, 0xd2, 0x6f, 0x4f, 0x9d, 0xd2, 0xc5, 0x41, 0xe1, 0xf4, - 0xa1, 0xe2, 0xb9, 0x37, 0x80, 0x3e, 0x77, 0xf4, 0xfb, 0x38, 0xdf, 0xff, 0xd8, 0xf9, 0x2e, 0x7f, - 0x25, 0x55, 0x36, 0xff, 0xa5, 0x7a, 0x22, 0x3f, 0xfa, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x6c, 0xe3, - 0xc7, 0xd8, 0xec, 0x07, 0x00, 0x00, + // 838 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xcf, 0xc6, 0x55, 0xdb, 0xbc, 0x38, 0xb1, 0xb3, 0x42, 0xc5, 0xb1, 0x2c, 0xdb, 0x6c, 0x11, + 0x54, 0x48, 0xdd, 0x55, 0x02, 0x42, 0x20, 0x2e, 0x25, 0x89, 0x50, 0x2d, 0x39, 0x48, 0xac, 0x1b, + 0x0e, 0xb9, 0xac, 0x66, 0x77, 0x46, 0xf6, 0xc8, 0xbb, 0x33, 0xee, 0xce, 0xd8, 0xa5, 0xfd, 0x04, + 0x1c, 0x7b, 0xe5, 0x23, 0xc0, 0x85, 0x4f, 0xc0, 0x85, 0x53, 0x8f, 0x3d, 0x22, 0x0e, 0x05, 0x25, + 0x5f, 0x04, 0xcd, 0xec, 0xec, 0x1f, 0xdb, 0x50, 0xe1, 0xf4, 0x64, 0xef, 0x9b, 0xdf, 0xcc, 0x7b, + 0xbf, 0xdf, 0xef, 0xbd, 0x19, 0xe8, 0x09, 0x99, 0x52, 0x4c, 0x3c, 0x21, 0xd1, 0x94, 0xd0, 0x30, + 0xf2, 0x22, 0x14, 0xc7, 0x21, 0x8a, 0xa6, 0xc2, 0x9d, 0xa5, 0x5c, 0x72, 0xbb, 0x91, 0x01, 0xdc, + 0x1c, 0xd0, 0x7e, 0x6f, 0xcc, 0xc7, 0x5c, 0xaf, 0x79, 0xea, 0x5f, 0x06, 0x6b, 0x77, 0x23, 0x2e, + 0x12, 0x2e, 0xbc, 0x10, 0x09, 0xe2, 0x2d, 0x8e, 0x42, 0x22, 0xd1, 0x91, 0x17, 0x71, 0xca, 0xcc, + 0x7a, 0xc7, 0xe4, 0x49, 0x49, 0xc4, 0x53, 0x2c, 0xf2, 0x5f, 0xb3, 0xba, 0x56, 0xc5, 0x84, 0x0b, + 0x19, 0xbc, 0xe0, 0x8c, 0xfc, 0x17, 0x60, 0x81, 0x62, 0x8a, 0x91, 0xe4, 0x69, 0x06, 0x70, 0x9e, + 0x41, 0x63, 0x34, 0x8b, 0xa9, 0x3c, 0x23, 0x31, 0x19, 0x23, 0x49, 0x39, 0xb3, 0x3b, 0xb0, 0x53, + 0xa0, 0x5a, 0x56, 0xdf, 0x7a, 0xb0, 0xe3, 0x97, 0x01, 0xfb, 0x1b, 0xb8, 0x8d, 0x12, 0x3e, 0x67, + 0xb2, 0xb5, 0xad, 0x96, 0x4e, 0xdc, 0x57, 0x6f, 0x7a, 0x5b, 0x7f, 0xbe, 0xe9, 0x7d, 0x34, 0xa6, + 0x72, 0x32, 0x0f, 0xdd, 0x88, 0x27, 0x9e, 0xe1, 0x94, 0xfd, 0x3c, 0x14, 0x78, 0xea, 0xc9, 0xe7, + 0x33, 0x22, 0xdc, 0x01, 0x93, 0xbe, 0xd9, 0xed, 0xfc, 0x6a, 0x41, 0xd3, 0x24, 0x25, 0xa7, 0x46, + 0x3b, 0xbb, 0x0f, 0xf5, 0x82, 0x41, 0x40, 0xb1, 0xc9, 0x0e, 0x2a, 0x76, 0xc9, 0x19, 0x19, 0x60, + 0xfb, 0x13, 0x38, 0xc0, 0x64, 0xc6, 0x05, 0x95, 0x41, 0x26, 0x85, 0x82, 0xa9, 0x4a, 0x6e, 0xf9, + 0x0d, 0xb3, 0xe0, 0xeb, 0xf8, 0x00, 0xdb, 0xe7, 0x70, 0x20, 0x14, 0xb7, 0x00, 0x17, 0xe4, 0x44, + 0xab, 0xd6, 0xaf, 0x3d, 0xd8, 0x3d, 0xee, 0xbb, 0x2b, 0xf6, 0xb8, 0x2b, 0x2a, 0xf8, 0x4d, 0xb1, + 0x1c, 0x10, 0xce, 0x8f, 0x16, 0xec, 0x9d, 0xc6, 0x88, 0x26, 0x45, 0xb9, 0x5f, 0xc2, 0xe1, 0x5c, + 0x90, 0x34, 0x48, 0x09, 0x26, 0xc9, 0x4c, 0xa1, 0x2a, 0x45, 0x65, 0xb5, 0xdf, 0x53, 0x00, 0xbf, + 0x58, 0x2f, 0x6a, 0x3b, 0x84, 0xbb, 0xd1, 0x04, 0x51, 0x96, 0x97, 0xbf, 0xe3, 0xdf, 0xd1, 0xdf, + 0x03, 0x6c, 0x7f, 0x00, 0x75, 0x32, 0xe3, 0xd1, 0x24, 0x60, 0xf3, 0x24, 0x24, 0x69, 0xab, 0xa6, + 0xd9, 0xed, 0xea, 0xd8, 0xb7, 0x3a, 0xe4, 0xfc, 0x6c, 0x41, 0xd3, 0x27, 0x94, 0x2d, 0x88, 0x90, + 0x45, 0x35, 0x02, 0x1a, 0xa9, 0x89, 0x05, 0xc6, 0x22, 0x55, 0xc3, 0xee, 0xf1, 0xa1, 0x9b, 0x39, + 0xe1, 0xaa, 0x26, 0x73, 0x4d, 0x93, 0xb9, 0xa7, 0x9c, 0xb2, 0x13, 0x4f, 0xb9, 0xf7, 0xcb, 0x5f, + 0xbd, 0x8f, 0xff, 0x87, 0x7b, 0x6a, 0x83, 0xbf, 0x9f, 0xa7, 0xf8, 0x5a, 0x67, 0x58, 0x73, 0xac, + 0xb6, 0xea, 0x98, 0xf3, 0xbb, 0x05, 0xf6, 0x05, 0xc3, 0x9b, 0x5b, 0xfd, 0xaf, 0xf6, 0x6d, 0xdf, + 0xd4, 0x3e, 0xfb, 0x2b, 0x68, 0x67, 0xb2, 0xce, 0x59, 0xc8, 0x19, 0xa6, 0x6c, 0x5c, 0x9a, 0x95, + 0xb5, 0xc5, 0x2d, 0xff, 0x7d, 0x8d, 0xb8, 0xc8, 0x01, 0xb9, 0x5b, 0xc2, 0xb9, 0x84, 0x7b, 0x25, + 0x87, 0xc7, 0xbc, 0xa2, 0xfa, 0x23, 0xa8, 0xa1, 0x24, 0x53, 0x7a, 0xf3, 0x61, 0x50, 0x5b, 0x1d, + 0x01, 0x76, 0xd9, 0x20, 0x1b, 0xe8, 0xf3, 0x76, 0x42, 0xdb, 0x6f, 0x27, 0xf4, 0x93, 0x05, 0xbb, + 0x3e, 0x09, 0x51, 0x8c, 0x58, 0x44, 0xd9, 0xd8, 0xbe, 0x0f, 0x7b, 0x22, 0x8d, 0x82, 0xd5, 0xc1, + 0xaf, 0x8b, 0x34, 0xfa, 0xbe, 0x98, 0xfd, 0xfb, 0xb0, 0x87, 0x85, 0xac, 0x80, 0xb2, 0xce, 0xad, + 0x63, 0x21, 0x4b, 0x90, 0x11, 0xa4, 0x76, 0x73, 0x41, 0x9e, 0xc1, 0x41, 0x5e, 0xda, 0x26, 0xfd, + 0xf2, 0x08, 0xea, 0x69, 0xc9, 0x28, 0x6f, 0x95, 0xce, 0x5a, 0xab, 0x54, 0x68, 0xfb, 0x4b, 0x3b, + 0x9c, 0x0b, 0x68, 0x9d, 0x11, 0xc9, 0xa7, 0x84, 0xd1, 0x17, 0x64, 0x34, 0x41, 0x29, 0x11, 0x95, + 0x59, 0xbf, 0x63, 0xee, 0x17, 0x33, 0x55, 0xbd, 0xfc, 0xe0, 0xfc, 0x4a, 0x1e, 0x8e, 0xce, 0x9f, + 0xa8, 0xbd, 0x67, 0xe6, 0x1a, 0xca, 0xf1, 0xce, 0x6f, 0x16, 0xec, 0x0f, 0x47, 0xe7, 0x43, 0xfa, + 0x74, 0x4e, 0xf1, 0x48, 0x95, 0xf1, 0x0e, 0xa7, 0xd9, 0x9f, 0xc3, 0x4e, 0x21, 0x84, 0x36, 0x40, + 0x0d, 0xf8, 0x2a, 0xc7, 0xc7, 0x46, 0x16, 0xff, 0x6e, 0x2e, 0x90, 0xfd, 0x45, 0xf5, 0x5a, 0xaf, + 0xe9, 0x7d, 0xed, 0xb5, 0x7d, 0x85, 0x8d, 0x95, 0x2b, 0xdf, 0x79, 0x0a, 0x1f, 0x16, 0xf1, 0x4c, + 0x95, 0x27, 0x5c, 0xd7, 0x26, 0xbe, 0x9b, 0x93, 0xf4, 0x79, 0x21, 0xd1, 0x00, 0x9a, 0xb1, 0x48, + 0x82, 0x58, 0xf3, 0x0c, 0xf4, 0x99, 0xab, 0xec, 0x8a, 0x44, 0xcb, 0x7a, 0xf8, 0xfb, 0xb1, 0x48, + 0x2a, 0xdf, 0xce, 0x4b, 0x0b, 0x3a, 0x66, 0x78, 0xf3, 0x9c, 0xcb, 0xb9, 0x66, 0xd0, 0xa1, 0x8c, + 0x4a, 0x8a, 0xe2, 0xb2, 0x1d, 0x2b, 0x17, 0xc5, 0x0d, 0xe7, 0xb1, 0x6d, 0xce, 0x2c, 0xe8, 0x96, + 0x17, 0xc8, 0xc9, 0xf0, 0xd5, 0x55, 0xd7, 0x7a, 0x7d, 0xd5, 0xb5, 0xfe, 0xbe, 0xea, 0x5a, 0x2f, + 0xaf, 0xbb, 0x5b, 0xaf, 0xaf, 0xbb, 0x5b, 0x7f, 0x5c, 0x77, 0xb7, 0x2e, 0x8f, 0x2b, 0xa7, 0x8f, + 0x34, 0xcf, 0x87, 0x43, 0x14, 0x0a, 0xcf, 0xbc, 0xbd, 0x8b, 0xa3, 0xcf, 0xbc, 0x1f, 0xca, 0x17, + 0x58, 0x67, 0x0b, 0x6f, 0xeb, 0xe7, 0xf7, 0xd3, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x4b, 0x54, + 0xb4, 0x06, 0x48, 0x08, 0x00, 0x00, } func (m *SplitDelegation) Marshal() (dAtA []byte, err error) { @@ -952,6 +991,39 @@ func (m *UndelegateCallback) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *UndelegateHostCallback) 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 *UndelegateHostCallback) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UndelegateHostCallback) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.Amt.Size() + i -= size + if _, err := m.Amt.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintCallbacks(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *RedemptionCallback) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1362,6 +1434,17 @@ func (m *UndelegateCallback) Size() (n int) { return n } +func (m *UndelegateHostCallback) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Amt.Size() + n += 1 + l + sovCallbacks(uint64(l)) + return n +} + func (m *RedemptionCallback) Size() (n int) { if m == nil { return 0 @@ -2175,6 +2258,90 @@ func (m *UndelegateCallback) Unmarshal(dAtA []byte) error { } return nil } +func (m *UndelegateHostCallback) 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 ErrIntOverflowCallbacks + } + 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: UndelegateHostCallback: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UndelegateHostCallback: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amt", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCallbacks + } + 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 ErrInvalidLengthCallbacks + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCallbacks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCallbacks(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCallbacks + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *RedemptionCallback) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 From 6cdf5d7955de8a8486166f13ce77f429eae0d4a9 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 11:19:45 -0400 Subject: [PATCH 08/27] isCallable -> isPrevented --- x/stakeibc/keeper/icacallbacks_undelegate.go | 7 +++---- x/stakeibc/keeper/msg_undelegate_host.go | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/x/stakeibc/keeper/icacallbacks_undelegate.go b/x/stakeibc/keeper/icacallbacks_undelegate.go index a8f3965030..ec2c09adbb 100644 --- a/x/stakeibc/keeper/icacallbacks_undelegate.go +++ b/x/stakeibc/keeper/icacallbacks_undelegate.go @@ -237,7 +237,7 @@ func (k Keeper) BurnTokens(ctx sdk.Context, hostZone types.HostZone, stTokenBurn // ICA Callback after undelegating host // // If successful: -// * sets isCallable = false +// * sets isPrevented = true // If timeout: // * Does nothing // If failure: @@ -264,9 +264,8 @@ func (k Keeper) UndelegateHostCallback(ctx sdk.Context, packet channeltypes.Pack k.Logger(ctx).Info("UndelegateHostCallback success:", icacallbackstypes.AckResponseStatus_SUCCESS, packet) - // TODO set isCallable = false - // log "isCallable has been set to false" - k.Logger(ctx).Info(">>>>>>>>>>> isCallable has been set to false. <<<<<<<<<<<<<<<") + // TODO set isPrevented = true + k.Logger(ctx).Info(">>>>>>>>>>> isPrevented has been set to true <<<<<<<<<<<<<<<") return nil } diff --git a/x/stakeibc/keeper/msg_undelegate_host.go b/x/stakeibc/keeper/msg_undelegate_host.go index 39d93f3664..5694e65a5e 100644 --- a/x/stakeibc/keeper/msg_undelegate_host.go +++ b/x/stakeibc/keeper/msg_undelegate_host.go @@ -11,14 +11,14 @@ import ( ) const ( - isCallable = true + isPrevented = true ) func (k msgServer) UndelegateHost(goCtx context.Context, msg *types.MsgUndelegateHost) (*types.MsgUndelegateHostResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) // undelegateHost is callable only if it has not yet been called and succeeded - if !isCallable { + if !isPrevented { return nil, errorsmod.Wrapf(types.ErrUndelegateHostNotCallable, "") } From cc5c91a0277893082f96a59abefc2d8808c26db5 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 12:13:43 -0400 Subject: [PATCH 09/27] isPrevented -> UndelegateHostPreventedKey, add helpers --- x/stakeibc/keeper/icacallbacks_undelegate.go | 8 +++--- x/stakeibc/keeper/msg_undelegate_host.go | 27 +++++++++++++++++--- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/x/stakeibc/keeper/icacallbacks_undelegate.go b/x/stakeibc/keeper/icacallbacks_undelegate.go index ec2c09adbb..774b3725eb 100644 --- a/x/stakeibc/keeper/icacallbacks_undelegate.go +++ b/x/stakeibc/keeper/icacallbacks_undelegate.go @@ -237,7 +237,7 @@ func (k Keeper) BurnTokens(ctx sdk.Context, hostZone types.HostZone, stTokenBurn // ICA Callback after undelegating host // // If successful: -// * sets isPrevented = true +// * sets SetUndelegateHostPrevented // If timeout: // * Does nothing // If failure: @@ -264,8 +264,10 @@ func (k Keeper) UndelegateHostCallback(ctx sdk.Context, packet channeltypes.Pack k.Logger(ctx).Info("UndelegateHostCallback success:", icacallbackstypes.AckResponseStatus_SUCCESS, packet) - // TODO set isPrevented = true - k.Logger(ctx).Info(">>>>>>>>>>> isPrevented has been set to true <<<<<<<<<<<<<<<") + k.Logger(ctx).Info(">>>>>>>>>>> SetUndelegateHostPrevented <<<<<<<<<<<<<<<") + if err := k.SetUndelegateHostPrevented(ctx); err != nil { + return err + } return nil } diff --git a/x/stakeibc/keeper/msg_undelegate_host.go b/x/stakeibc/keeper/msg_undelegate_host.go index 5694e65a5e..6547b3511b 100644 --- a/x/stakeibc/keeper/msg_undelegate_host.go +++ b/x/stakeibc/keeper/msg_undelegate_host.go @@ -10,15 +10,13 @@ import ( "github.com/Stride-Labs/stride/v14/x/stakeibc/types" ) -const ( - isPrevented = true -) +const isUndelegateHostPreventedKey = "is-undelegate-host-prevented" func (k msgServer) UndelegateHost(goCtx context.Context, msg *types.MsgUndelegateHost) (*types.MsgUndelegateHostResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) // undelegateHost is callable only if it has not yet been called and succeeded - if !isPrevented { + if k.IsUndelegateHostPrevented(ctx) { return nil, errorsmod.Wrapf(types.ErrUndelegateHostNotCallable, "") } @@ -32,3 +30,24 @@ func (k msgServer) UndelegateHost(goCtx context.Context, msg *types.MsgUndelegat return &types.MsgUndelegateHostResponse{}, nil } + +func (k Keeper) SetUndelegateHostPrevented(ctx sdk.Context) error { + + store := ctx.KVStore(k.storeKey) + + // set the key to 1 if it's not set + if !k.IsUndelegateHostPrevented(ctx) { + store.Set([]byte(isUndelegateHostPreventedKey), []byte{1}) + } + return nil +} + +func (k Keeper) IsUndelegateHostPrevented(ctx sdk.Context) bool { + store := ctx.KVStore(k.storeKey) + if !store.Has([]byte(isUndelegateHostPreventedKey)) { + return false + } + + value := store.Get([]byte(isUndelegateHostPreventedKey)) + return len(value) == 1 && value[0] == 1 +} From a3a895a10e7e461bbf1b0f475fb2849ea05f95e1 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 12:19:48 -0400 Subject: [PATCH 10/27] undelegate host shold propagate evmos error --- x/stakeibc/keeper/msg_undelegate_host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stakeibc/keeper/msg_undelegate_host.go b/x/stakeibc/keeper/msg_undelegate_host.go index 6547b3511b..61be4d1d2b 100644 --- a/x/stakeibc/keeper/msg_undelegate_host.go +++ b/x/stakeibc/keeper/msg_undelegate_host.go @@ -22,7 +22,7 @@ func (k msgServer) UndelegateHost(goCtx context.Context, msg *types.MsgUndelegat // Get host zone unbonding message by summing up the unbonding records if err := k.UndelegateHostEvmos(ctx, msg.Amount); err != nil { - k.Logger(ctx).Error(fmt.Sprintf("Error initiating host zone unbondings for UndelegateHostEvmos", err.Error())) + return nil, fmt.Errorf("Error initiating host zone unbondings for UndelegateHostEvmos %s", err.Error()) } // log: issuing an undelegation to Evmos From f5ae9e12eb3447de628f707ade30850fff5bb947 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 12:27:08 -0400 Subject: [PATCH 11/27] for reviewer: copy over UnbondFromHostZone in place of UndelegateHostEvmos --- x/stakeibc/keeper/undelegate_host.go | 79 ++++++++++++++-------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/x/stakeibc/keeper/undelegate_host.go b/x/stakeibc/keeper/undelegate_host.go index 8dd06b561b..14e8f1ca67 100644 --- a/x/stakeibc/keeper/undelegate_host.go +++ b/x/stakeibc/keeper/undelegate_host.go @@ -4,12 +4,12 @@ import ( "fmt" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/gogoproto/proto" "github.com/Stride-Labs/stride/v14/utils" + recordstypes "github.com/Stride-Labs/stride/v14/x/records/types" "github.com/Stride-Labs/stride/v14/x/stakeibc/types" ) @@ -18,54 +18,41 @@ const ( EvmosHostZoneChainId = "GAIA" // "evmos-9001_2" // TODO: set value to "evmos-9001_2", remove this hardcoded value ) -// Submits undelegation ICA message for Evmos -// The total unbond amount is input, capped at MaxNumTokensUnbondable. -func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) error { +func (k Keeper) UnbondFromHostZone(ctx sdk.Context, hostZone types.HostZone) error { + k.Logger(ctx).Info(utils.LogWithHostZone(hostZone.ChainId, + "Preparing MsgUndelegates from the delegation account to each validator")) - // Get the host zone - evmosHost, found := k.GetHostZone(ctx, EvmosHostZoneChainId) - if !found { - return errorsmod.Wrapf(types.ErrHostZoneNotFound, "host zone %s not found", EvmosHostZoneChainId) + // Confirm the delegation account was registered + if hostZone.DelegationIcaAddress == "" { + return errorsmod.Wrapf(types.ErrICAAccountNotFound, "no delegation account found for %s", hostZone.ChainId) } - k.Logger(ctx).Info(utils.LogWithHostZone(evmosHost.ChainId, - "Total unbonded amount: %v%s", totalUnbondAmount, evmosHost.HostDenom)) + // Iterate through every unbonding record and sum the total amount to unbond for the given host zone + totalUnbondAmount, epochUnbondingRecordIds := k.GetTotalUnbondAmountAndRecordsIds(ctx, hostZone.ChainId) + k.Logger(ctx).Info(utils.LogWithHostZone(hostZone.ChainId, + "Total unbonded amount: %v%s", totalUnbondAmount, hostZone.HostDenom)) // If there's nothing to unbond, return and move on to the next host zone if totalUnbondAmount.IsZero() { return nil } - // if the total unbond amount is greater than the max, exit - // TODO: this overflows above ~100e18, NEED NEW TYPE - if totalUnbondAmount.GT(math.NewInt(MaxNumTokensUnbondable)) { - return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "total unbond amount %v%s is greater than MaxNumTokensUnbondable %v%s", - totalUnbondAmount, evmosHost.HostDenom, MaxNumTokensUnbondable, evmosHost.HostDenom) - } - - k.Logger(ctx).Info("Preparing MsgUndelegates from the delegation account to each validator on Evmos") - - // Confirm the delegation account was registered - if evmosHost.DelegationIcaAddress == "" { - return errorsmod.Wrapf(types.ErrICAAccountNotFound, "no delegation account found for %s", evmosHost.ChainId) - } - // Determine the ideal balanced delegation for each validator after the unbonding // (as if we were to unbond and then rebalance) // This will serve as the starting point for determining how much to unbond each validator - delegationAfterUnbonding := evmosHost.TotalDelegations.Sub(totalUnbondAmount) - balancedDelegationsAfterUnbonding, err := k.GetTargetValAmtsForHostZone(ctx, evmosHost, delegationAfterUnbonding) + delegationAfterUnbonding := hostZone.TotalDelegations.Sub(totalUnbondAmount) + balancedDelegationsAfterUnbonding, err := k.GetTargetValAmtsForHostZone(ctx, hostZone, delegationAfterUnbonding) if err != nil { - return errorsmod.Wrapf(err, "unable to get target val amounts for host zone %s", evmosHost.ChainId) + return errorsmod.Wrapf(err, "unable to get target val amounts for host zone %s", hostZone.ChainId) } // Determine the unbond capacity for each validator // Each validator can only unbond up to the difference between their current delegation and their balanced delegation // The validator's current delegation will be above their balanced delegation if they've received LSM Liquid Stakes // (which is only rebalanced once per unbonding period) - validatorUnbondCapacity := k.GetValidatorUnbondCapacity(ctx, evmosHost.Validators, balancedDelegationsAfterUnbonding) + validatorUnbondCapacity := k.GetValidatorUnbondCapacity(ctx, hostZone.Validators, balancedDelegationsAfterUnbonding) if len(validatorUnbondCapacity) == 0 { - return fmt.Errorf("there are no validators on %s with sufficient unbond capacity", evmosHost.ChainId) + return fmt.Errorf("there are no validators on %s with sufficient unbond capacity", hostZone.ChainId) } // Sort the unbonding capacity by priority @@ -77,7 +64,7 @@ func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) } // Get the undelegation ICA messages and split delegations for the callback - msgs, unbondings, err := k.GetUnbondingICAMessages(evmosHost, totalUnbondAmount, prioritizedUnbondCapacity) + msgs, unbondings, err := k.GetUnbondingICAMessages(hostZone, totalUnbondAmount, prioritizedUnbondCapacity) if err != nil { return err } @@ -98,36 +85,48 @@ func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) unbondingsBatch := unbondings[start:end] // Store the callback data - undelegateHostCallback := types.UndelegateHostCallback{ - Amt: totalUnbondAmount, + undelegateCallback := types.UndelegateCallback{ + HostZoneId: hostZone.ChainId, + SplitDelegations: unbondingsBatch, + EpochUnbondingRecordIds: epochUnbondingRecordIds, } - callbackArgsBz, err := proto.Marshal(&undelegateHostCallback) + callbackArgsBz, err := proto.Marshal(&undelegateCallback) if err != nil { - return errorsmod.Wrap(err, "unable to marshal undelegate host callback args") + return errorsmod.Wrap(err, "unable to marshal undelegate callback args") } // Submit the undelegation ICA if _, err := k.SubmitTxsDayEpoch( ctx, - evmosHost.ConnectionId, + hostZone.ConnectionId, msgsBatch, types.ICAAccountType_DELEGATION, - ICACallbackID_UndelegateHost, + ICACallbackID_Undelegate, callbackArgsBz, ); err != nil { - return errorsmod.Wrapf(err, "unable to submit unbonding ICA for %s", evmosHost.ChainId) + return errorsmod.Wrapf(err, "unable to submit unbonding ICA for %s", hostZone.ChainId) } // flag the delegation change in progress on each validator for _, unbonding := range unbondingsBatch { - if err := k.IncrementValidatorDelegationChangesInProgress(&evmosHost, unbonding.Validator); err != nil { + if err := k.IncrementValidatorDelegationChangesInProgress(&hostZone, unbonding.Validator); err != nil { return err } } - k.SetHostZone(ctx, evmosHost) + k.SetHostZone(ctx, hostZone) + } + + // Update the epoch unbonding record status + if err := k.RecordsKeeper.SetHostZoneUnbondings( + ctx, + hostZone.ChainId, + epochUnbondingRecordIds, + recordstypes.HostZoneUnbonding_UNBONDING_IN_PROGRESS, + ); err != nil { + return err } - EmitUndelegationEvent(ctx, evmosHost, totalUnbondAmount) + EmitUndelegationEvent(ctx, hostZone, totalUnbondAmount) return nil } From 6e8be69195abf9b09a002808f2dc604b5a0aafe4 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 12:28:01 -0400 Subject: [PATCH 12/27] for reviewer: UndelegateHostEvmos (diffs vs UnbondFromHostZone) --- x/stakeibc/keeper/undelegate_host.go | 72 ++++++++++++++-------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/x/stakeibc/keeper/undelegate_host.go b/x/stakeibc/keeper/undelegate_host.go index 14e8f1ca67..a554f548b3 100644 --- a/x/stakeibc/keeper/undelegate_host.go +++ b/x/stakeibc/keeper/undelegate_host.go @@ -4,12 +4,12 @@ import ( "fmt" errorsmod "cosmossdk.io/errors" + "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/gogoproto/proto" "github.com/Stride-Labs/stride/v14/utils" - recordstypes "github.com/Stride-Labs/stride/v14/x/records/types" "github.com/Stride-Labs/stride/v14/x/stakeibc/types" ) @@ -18,41 +18,54 @@ const ( EvmosHostZoneChainId = "GAIA" // "evmos-9001_2" // TODO: set value to "evmos-9001_2", remove this hardcoded value ) -func (k Keeper) UnbondFromHostZone(ctx sdk.Context, hostZone types.HostZone) error { - k.Logger(ctx).Info(utils.LogWithHostZone(hostZone.ChainId, - "Preparing MsgUndelegates from the delegation account to each validator")) +// Submits undelegation ICA message for Evmos +// The total unbond amount is input, capped at MaxNumTokensUnbondable. +func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) error { - // Confirm the delegation account was registered - if hostZone.DelegationIcaAddress == "" { - return errorsmod.Wrapf(types.ErrICAAccountNotFound, "no delegation account found for %s", hostZone.ChainId) + // Get the host zone + evmosHost, found := k.GetHostZone(ctx, EvmosHostZoneChainId) + if !found { + return errorsmod.Wrapf(types.ErrHostZoneNotFound, "host zone %s not found", EvmosHostZoneChainId) } - // Iterate through every unbonding record and sum the total amount to unbond for the given host zone - totalUnbondAmount, epochUnbondingRecordIds := k.GetTotalUnbondAmountAndRecordsIds(ctx, hostZone.ChainId) - k.Logger(ctx).Info(utils.LogWithHostZone(hostZone.ChainId, - "Total unbonded amount: %v%s", totalUnbondAmount, hostZone.HostDenom)) + k.Logger(ctx).Info(utils.LogWithHostZone(evmosHost.ChainId, + "Total unbonded amount: %v%s", totalUnbondAmount, evmosHost.HostDenom)) // If there's nothing to unbond, return and move on to the next host zone if totalUnbondAmount.IsZero() { return nil } + // if the total unbond amount is greater than the max, exit + // TODO: this overflows above ~100e18, NEED NEW TYPE + if totalUnbondAmount.GT(math.NewInt(MaxNumTokensUnbondable)) { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "total unbond amount %v%s is greater than MaxNumTokensUnbondable %v%s", + totalUnbondAmount, evmosHost.HostDenom, MaxNumTokensUnbondable, evmosHost.HostDenom) + } + + k.Logger(ctx).Info("Preparing MsgUndelegates from the delegation account to each validator on Evmos") + + // Confirm the delegation account was registered + if evmosHost.DelegationIcaAddress == "" { + return errorsmod.Wrapf(types.ErrICAAccountNotFound, "no delegation account found for %s", evmosHost.ChainId) + } + // Determine the ideal balanced delegation for each validator after the unbonding // (as if we were to unbond and then rebalance) // This will serve as the starting point for determining how much to unbond each validator - delegationAfterUnbonding := hostZone.TotalDelegations.Sub(totalUnbondAmount) - balancedDelegationsAfterUnbonding, err := k.GetTargetValAmtsForHostZone(ctx, hostZone, delegationAfterUnbonding) + delegationAfterUnbonding := evmosHost.TotalDelegations.Sub(totalUnbondAmount) + balancedDelegationsAfterUnbonding, err := k.GetTargetValAmtsForHostZone(ctx, evmosHost, delegationAfterUnbonding) if err != nil { - return errorsmod.Wrapf(err, "unable to get target val amounts for host zone %s", hostZone.ChainId) + return errorsmod.Wrapf(err, "unable to get target val amounts for host zone %s", evmosHost.ChainId) } // Determine the unbond capacity for each validator // Each validator can only unbond up to the difference between their current delegation and their balanced delegation // The validator's current delegation will be above their balanced delegation if they've received LSM Liquid Stakes // (which is only rebalanced once per unbonding period) - validatorUnbondCapacity := k.GetValidatorUnbondCapacity(ctx, hostZone.Validators, balancedDelegationsAfterUnbonding) + validatorUnbondCapacity := k.GetValidatorUnbondCapacity(ctx, evmosHost.Validators, balancedDelegationsAfterUnbonding) if len(validatorUnbondCapacity) == 0 { - return fmt.Errorf("there are no validators on %s with sufficient unbond capacity", hostZone.ChainId) + return fmt.Errorf("there are no validators on %s with sufficient unbond capacity", evmosHost.ChainId) } // Sort the unbonding capacity by priority @@ -64,7 +77,7 @@ func (k Keeper) UnbondFromHostZone(ctx sdk.Context, hostZone types.HostZone) err } // Get the undelegation ICA messages and split delegations for the callback - msgs, unbondings, err := k.GetUnbondingICAMessages(hostZone, totalUnbondAmount, prioritizedUnbondCapacity) + msgs, unbondings, err := k.GetUnbondingICAMessages(evmosHost, totalUnbondAmount, prioritizedUnbondCapacity) if err != nil { return err } @@ -86,9 +99,8 @@ func (k Keeper) UnbondFromHostZone(ctx sdk.Context, hostZone types.HostZone) err // Store the callback data undelegateCallback := types.UndelegateCallback{ - HostZoneId: hostZone.ChainId, - SplitDelegations: unbondingsBatch, - EpochUnbondingRecordIds: epochUnbondingRecordIds, + HostZoneId: evmosHost.ChainId, + SplitDelegations: unbondingsBatch, } callbackArgsBz, err := proto.Marshal(&undelegateCallback) if err != nil { @@ -98,35 +110,25 @@ func (k Keeper) UnbondFromHostZone(ctx sdk.Context, hostZone types.HostZone) err // Submit the undelegation ICA if _, err := k.SubmitTxsDayEpoch( ctx, - hostZone.ConnectionId, + evmosHost.ConnectionId, msgsBatch, types.ICAAccountType_DELEGATION, ICACallbackID_Undelegate, callbackArgsBz, ); err != nil { - return errorsmod.Wrapf(err, "unable to submit unbonding ICA for %s", hostZone.ChainId) + return errorsmod.Wrapf(err, "unable to submit unbonding ICA for %s", evmosHost.ChainId) } // flag the delegation change in progress on each validator for _, unbonding := range unbondingsBatch { - if err := k.IncrementValidatorDelegationChangesInProgress(&hostZone, unbonding.Validator); err != nil { + if err := k.IncrementValidatorDelegationChangesInProgress(&evmosHost, unbonding.Validator); err != nil { return err } } - k.SetHostZone(ctx, hostZone) - } - - // Update the epoch unbonding record status - if err := k.RecordsKeeper.SetHostZoneUnbondings( - ctx, - hostZone.ChainId, - epochUnbondingRecordIds, - recordstypes.HostZoneUnbonding_UNBONDING_IN_PROGRESS, - ); err != nil { - return err + k.SetHostZone(ctx, evmosHost) } - EmitUndelegationEvent(ctx, hostZone, totalUnbondAmount) + EmitUndelegationEvent(ctx, evmosHost, totalUnbondAmount) return nil } From c02032ac83c5b362dff4d93fd7b2427d86600288 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 12:59:11 -0400 Subject: [PATCH 13/27] fix callback, add custom error, set EvmosHostZoneChainId for production --- x/stakeibc/keeper/undelegate_host.go | 11 +++++------ x/stakeibc/types/errors.go | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/x/stakeibc/keeper/undelegate_host.go b/x/stakeibc/keeper/undelegate_host.go index a554f548b3..80d8a6d55d 100644 --- a/x/stakeibc/keeper/undelegate_host.go +++ b/x/stakeibc/keeper/undelegate_host.go @@ -15,7 +15,7 @@ import ( const ( MaxNumTokensUnbondable = 1000000000000000000 // 1e18 - EvmosHostZoneChainId = "GAIA" // "evmos-9001_2" // TODO: set value to "evmos-9001_2", remove this hardcoded value + EvmosHostZoneChainId = "evmos_9001-2" ) // Submits undelegation ICA message for Evmos @@ -98,11 +98,10 @@ func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) unbondingsBatch := unbondings[start:end] // Store the callback data - undelegateCallback := types.UndelegateCallback{ - HostZoneId: evmosHost.ChainId, - SplitDelegations: unbondingsBatch, + undelegateHostCallback := types.UndelegateHostCallback{ + Amt: totalUnbondAmount, } - callbackArgsBz, err := proto.Marshal(&undelegateCallback) + callbackArgsBz, err := proto.Marshal(&undelegateHostCallback) if err != nil { return errorsmod.Wrap(err, "unable to marshal undelegate callback args") } @@ -113,7 +112,7 @@ func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) evmosHost.ConnectionId, msgsBatch, types.ICAAccountType_DELEGATION, - ICACallbackID_Undelegate, + ICACallbackID_UndelegateHost, callbackArgsBz, ); err != nil { return errorsmod.Wrapf(err, "unable to submit unbonding ICA for %s", evmosHost.ChainId) diff --git a/x/stakeibc/types/errors.go b/x/stakeibc/types/errors.go index 57a56148f3..c9f8c30d9a 100644 --- a/x/stakeibc/types/errors.go +++ b/x/stakeibc/types/errors.go @@ -56,5 +56,5 @@ var ( ErrInvalidValidatorDelegationUpdates = errorsmod.Register(ModuleName, 1548, "Invalid validator delegation updates") ErrLSMLiquidStakeDisabledForHostZone = errorsmod.Register(ModuleName, 1549, "LSM liquid stake is disabled for host zone") ErrUnableToRemoveValidator = errorsmod.Register(ModuleName, 1550, "Unable to remove validator") - ErrUndelegateHostNotCallable = errorsmod.Register(ModuleName, 1551, "Unable to call undelegate host") + ErrUndelegateHostNotCallable = errorsmod.Register(ModuleName, 1551, "Undelegate host is disabled") ) From f01f388f0bc995b092cfdc14392f6e168791e1c7 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 19:36:27 -0400 Subject: [PATCH 14/27] incr max to 100m and wrap in big int --- x/stakeibc/keeper/undelegate_host.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/x/stakeibc/keeper/undelegate_host.go b/x/stakeibc/keeper/undelegate_host.go index 80d8a6d55d..2241b8638d 100644 --- a/x/stakeibc/keeper/undelegate_host.go +++ b/x/stakeibc/keeper/undelegate_host.go @@ -14,8 +14,8 @@ import ( ) const ( - MaxNumTokensUnbondable = 1000000000000000000 // 1e18 - EvmosHostZoneChainId = "evmos_9001-2" + MaxNumTokensUnbondableStr = "1000000000000000000000000000" // 1e18 + EvmosHostZoneChainId = "evmos_9001-2" ) // Submits undelegation ICA message for Evmos @@ -38,7 +38,11 @@ func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) // if the total unbond amount is greater than the max, exit // TODO: this overflows above ~100e18, NEED NEW TYPE - if totalUnbondAmount.GT(math.NewInt(MaxNumTokensUnbondable)) { + MaxNumTokensUnbondable, found := math.NewIntFromString(MaxNumTokensUnbondableStr) + if !found { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "unable to parse MaxNumTokensUnbondable %s", MaxNumTokensUnbondable) + } + if totalUnbondAmount.GT(MaxNumTokensUnbondable) { return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "total unbond amount %v%s is greater than MaxNumTokensUnbondable %v%s", totalUnbondAmount, evmosHost.HostDenom, MaxNumTokensUnbondable, evmosHost.HostDenom) } From fb33de352750ca347eed731739250e8f27e23f62 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 19:49:01 -0400 Subject: [PATCH 15/27] flow splitDelegations through to callback, and copy UpdateDelegationBalances --- proto/stride/stakeibc/callbacks.proto | 1 + x/stakeibc/keeper/icacallbacks_undelegate.go | 26 +++ x/stakeibc/keeper/undelegate_host.go | 3 +- x/stakeibc/types/callbacks.pb.go | 172 +++++++++++++------ 4 files changed, 146 insertions(+), 56 deletions(-) diff --git a/proto/stride/stakeibc/callbacks.proto b/proto/stride/stakeibc/callbacks.proto index e0ecb6f9ea..5656f6b1de 100644 --- a/proto/stride/stakeibc/callbacks.proto +++ b/proto/stride/stakeibc/callbacks.proto @@ -47,6 +47,7 @@ message UndelegateHostCallback { (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false ]; + repeated SplitDelegation split_delegations = 2; } message RedemptionCallback { diff --git a/x/stakeibc/keeper/icacallbacks_undelegate.go b/x/stakeibc/keeper/icacallbacks_undelegate.go index 774b3725eb..ef987edbfb 100644 --- a/x/stakeibc/keeper/icacallbacks_undelegate.go +++ b/x/stakeibc/keeper/icacallbacks_undelegate.go @@ -262,6 +262,19 @@ func (k Keeper) UndelegateHostCallback(ctx sdk.Context, packet channeltypes.Pack return nil } + // Get the host zone + evmosHost, found := k.GetHostZone(ctx, EvmosHostZoneChainId) + if !found { + return errorsmod.Wrapf(types.ErrHostZoneNotFound, "host zone %s not found", EvmosHostZoneChainId) + } + + // Update delegation balances + err := k.UpdateDelegationBalances(ctx, evmosHost, undelegateHostCallback) + if err != nil { + k.Logger(ctx).Error(fmt.Sprintf("UndelegateCallback | %s", err.Error())) + return err + } + k.Logger(ctx).Info("UndelegateHostCallback success:", icacallbackstypes.AckResponseStatus_SUCCESS, packet) k.Logger(ctx).Info(">>>>>>>>>>> SetUndelegateHostPrevented <<<<<<<<<<<<<<<") @@ -271,3 +284,16 @@ func (k Keeper) UndelegateHostCallback(ctx sdk.Context, packet channeltypes.Pack return nil } + +// Decrement the delegation field on the host zone and each validator's delegations after a successful unbonding ICA +func (k Keeper) UpdateDelegationBalances(ctx sdk.Context, hostZone types.HostZone, undelegateCallback types.UndelegateCallback) error { + // Undelegate from each validator and update host zone staked balance, if successful + for _, undelegation := range undelegateCallback.SplitDelegations { + err := k.AddDelegationToValidator(ctx, &hostZone, undelegation.Validator, undelegation.Amount.Neg(), ICACallbackID_Undelegate) + if err != nil { + return err + } + } + k.SetHostZone(ctx, hostZone) + return nil +} diff --git a/x/stakeibc/keeper/undelegate_host.go b/x/stakeibc/keeper/undelegate_host.go index 2241b8638d..d85ed35c65 100644 --- a/x/stakeibc/keeper/undelegate_host.go +++ b/x/stakeibc/keeper/undelegate_host.go @@ -103,7 +103,8 @@ func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) // Store the callback data undelegateHostCallback := types.UndelegateHostCallback{ - Amt: totalUnbondAmount, + Amt: totalUnbondAmount, + SplitDelegations: unbondingsBatch, } callbackArgsBz, err := proto.Marshal(&undelegateHostCallback) if err != nil { diff --git a/x/stakeibc/types/callbacks.pb.go b/x/stakeibc/types/callbacks.pb.go index 1f7caa8af7..8d8b70cf94 100644 --- a/x/stakeibc/types/callbacks.pb.go +++ b/x/stakeibc/types/callbacks.pb.go @@ -304,7 +304,8 @@ func (m *UndelegateCallback) GetEpochUnbondingRecordIds() []uint64 { } type UndelegateHostCallback struct { - Amt github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,1,opt,name=amt,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"amt"` + Amt github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,1,opt,name=amt,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"amt"` + SplitDelegations []*SplitDelegation `protobuf:"bytes,2,rep,name=split_delegations,json=splitDelegations,proto3" json:"split_delegations,omitempty"` } func (m *UndelegateHostCallback) Reset() { *m = UndelegateHostCallback{} } @@ -340,6 +341,13 @@ func (m *UndelegateHostCallback) XXX_DiscardUnknown() { var xxx_messageInfo_UndelegateHostCallback proto.InternalMessageInfo +func (m *UndelegateHostCallback) GetSplitDelegations() []*SplitDelegation { + if m != nil { + return m.SplitDelegations + } + return nil +} + type RedemptionCallback struct { HostZoneId string `protobuf:"bytes,1,opt,name=host_zone_id,json=hostZoneId,proto3" json:"host_zone_id,omitempty"` EpochUnbondingRecordIds []uint64 `protobuf:"varint,2,rep,packed,name=epoch_unbonding_record_ids,json=epochUnbondingRecordIds,proto3" json:"epoch_unbonding_record_ids,omitempty"` @@ -702,60 +710,60 @@ func init() { func init() { proto.RegisterFile("stride/stakeibc/callbacks.proto", fileDescriptor_f41c99b09b96a5ac) } var fileDescriptor_f41c99b09b96a5ac = []byte{ - // 838 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0xcf, 0xc6, 0x55, 0xdb, 0xbc, 0x38, 0xb1, 0xb3, 0x42, 0xc5, 0xb1, 0x2c, 0xdb, 0x6c, 0x11, - 0x54, 0x48, 0xdd, 0x55, 0x02, 0x42, 0x20, 0x2e, 0x25, 0x89, 0x50, 0x2d, 0x39, 0x48, 0xac, 0x1b, - 0x0e, 0xb9, 0xac, 0x66, 0x77, 0x46, 0xf6, 0xc8, 0xbb, 0x33, 0xee, 0xce, 0xd8, 0xa5, 0xfd, 0x04, - 0x1c, 0x7b, 0xe5, 0x23, 0xc0, 0x85, 0x4f, 0xc0, 0x85, 0x53, 0x8f, 0x3d, 0x22, 0x0e, 0x05, 0x25, - 0x5f, 0x04, 0xcd, 0xec, 0xec, 0x1f, 0xdb, 0x50, 0xe1, 0xf4, 0x64, 0xef, 0x9b, 0xdf, 0xcc, 0x7b, - 0xbf, 0xdf, 0xef, 0xbd, 0x19, 0xe8, 0x09, 0x99, 0x52, 0x4c, 0x3c, 0x21, 0xd1, 0x94, 0xd0, 0x30, - 0xf2, 0x22, 0x14, 0xc7, 0x21, 0x8a, 0xa6, 0xc2, 0x9d, 0xa5, 0x5c, 0x72, 0xbb, 0x91, 0x01, 0xdc, - 0x1c, 0xd0, 0x7e, 0x6f, 0xcc, 0xc7, 0x5c, 0xaf, 0x79, 0xea, 0x5f, 0x06, 0x6b, 0x77, 0x23, 0x2e, - 0x12, 0x2e, 0xbc, 0x10, 0x09, 0xe2, 0x2d, 0x8e, 0x42, 0x22, 0xd1, 0x91, 0x17, 0x71, 0xca, 0xcc, - 0x7a, 0xc7, 0xe4, 0x49, 0x49, 0xc4, 0x53, 0x2c, 0xf2, 0x5f, 0xb3, 0xba, 0x56, 0xc5, 0x84, 0x0b, - 0x19, 0xbc, 0xe0, 0x8c, 0xfc, 0x17, 0x60, 0x81, 0x62, 0x8a, 0x91, 0xe4, 0x69, 0x06, 0x70, 0x9e, - 0x41, 0x63, 0x34, 0x8b, 0xa9, 0x3c, 0x23, 0x31, 0x19, 0x23, 0x49, 0x39, 0xb3, 0x3b, 0xb0, 0x53, - 0xa0, 0x5a, 0x56, 0xdf, 0x7a, 0xb0, 0xe3, 0x97, 0x01, 0xfb, 0x1b, 0xb8, 0x8d, 0x12, 0x3e, 0x67, - 0xb2, 0xb5, 0xad, 0x96, 0x4e, 0xdc, 0x57, 0x6f, 0x7a, 0x5b, 0x7f, 0xbe, 0xe9, 0x7d, 0x34, 0xa6, - 0x72, 0x32, 0x0f, 0xdd, 0x88, 0x27, 0x9e, 0xe1, 0x94, 0xfd, 0x3c, 0x14, 0x78, 0xea, 0xc9, 0xe7, - 0x33, 0x22, 0xdc, 0x01, 0x93, 0xbe, 0xd9, 0xed, 0xfc, 0x6a, 0x41, 0xd3, 0x24, 0x25, 0xa7, 0x46, - 0x3b, 0xbb, 0x0f, 0xf5, 0x82, 0x41, 0x40, 0xb1, 0xc9, 0x0e, 0x2a, 0x76, 0xc9, 0x19, 0x19, 0x60, - 0xfb, 0x13, 0x38, 0xc0, 0x64, 0xc6, 0x05, 0x95, 0x41, 0x26, 0x85, 0x82, 0xa9, 0x4a, 0x6e, 0xf9, - 0x0d, 0xb3, 0xe0, 0xeb, 0xf8, 0x00, 0xdb, 0xe7, 0x70, 0x20, 0x14, 0xb7, 0x00, 0x17, 0xe4, 0x44, - 0xab, 0xd6, 0xaf, 0x3d, 0xd8, 0x3d, 0xee, 0xbb, 0x2b, 0xf6, 0xb8, 0x2b, 0x2a, 0xf8, 0x4d, 0xb1, - 0x1c, 0x10, 0xce, 0x8f, 0x16, 0xec, 0x9d, 0xc6, 0x88, 0x26, 0x45, 0xb9, 0x5f, 0xc2, 0xe1, 0x5c, - 0x90, 0x34, 0x48, 0x09, 0x26, 0xc9, 0x4c, 0xa1, 0x2a, 0x45, 0x65, 0xb5, 0xdf, 0x53, 0x00, 0xbf, - 0x58, 0x2f, 0x6a, 0x3b, 0x84, 0xbb, 0xd1, 0x04, 0x51, 0x96, 0x97, 0xbf, 0xe3, 0xdf, 0xd1, 0xdf, - 0x03, 0x6c, 0x7f, 0x00, 0x75, 0x32, 0xe3, 0xd1, 0x24, 0x60, 0xf3, 0x24, 0x24, 0x69, 0xab, 0xa6, - 0xd9, 0xed, 0xea, 0xd8, 0xb7, 0x3a, 0xe4, 0xfc, 0x6c, 0x41, 0xd3, 0x27, 0x94, 0x2d, 0x88, 0x90, - 0x45, 0x35, 0x02, 0x1a, 0xa9, 0x89, 0x05, 0xc6, 0x22, 0x55, 0xc3, 0xee, 0xf1, 0xa1, 0x9b, 0x39, - 0xe1, 0xaa, 0x26, 0x73, 0x4d, 0x93, 0xb9, 0xa7, 0x9c, 0xb2, 0x13, 0x4f, 0xb9, 0xf7, 0xcb, 0x5f, - 0xbd, 0x8f, 0xff, 0x87, 0x7b, 0x6a, 0x83, 0xbf, 0x9f, 0xa7, 0xf8, 0x5a, 0x67, 0x58, 0x73, 0xac, - 0xb6, 0xea, 0x98, 0xf3, 0xbb, 0x05, 0xf6, 0x05, 0xc3, 0x9b, 0x5b, 0xfd, 0xaf, 0xf6, 0x6d, 0xdf, - 0xd4, 0x3e, 0xfb, 0x2b, 0x68, 0x67, 0xb2, 0xce, 0x59, 0xc8, 0x19, 0xa6, 0x6c, 0x5c, 0x9a, 0x95, - 0xb5, 0xc5, 0x2d, 0xff, 0x7d, 0x8d, 0xb8, 0xc8, 0x01, 0xb9, 0x5b, 0xc2, 0xb9, 0x84, 0x7b, 0x25, - 0x87, 0xc7, 0xbc, 0xa2, 0xfa, 0x23, 0xa8, 0xa1, 0x24, 0x53, 0x7a, 0xf3, 0x61, 0x50, 0x5b, 0x1d, - 0x01, 0x76, 0xd9, 0x20, 0x1b, 0xe8, 0xf3, 0x76, 0x42, 0xdb, 0x6f, 0x27, 0xf4, 0x93, 0x05, 0xbb, - 0x3e, 0x09, 0x51, 0x8c, 0x58, 0x44, 0xd9, 0xd8, 0xbe, 0x0f, 0x7b, 0x22, 0x8d, 0x82, 0xd5, 0xc1, - 0xaf, 0x8b, 0x34, 0xfa, 0xbe, 0x98, 0xfd, 0xfb, 0xb0, 0x87, 0x85, 0xac, 0x80, 0xb2, 0xce, 0xad, - 0x63, 0x21, 0x4b, 0x90, 0x11, 0xa4, 0x76, 0x73, 0x41, 0x9e, 0xc1, 0x41, 0x5e, 0xda, 0x26, 0xfd, - 0xf2, 0x08, 0xea, 0x69, 0xc9, 0x28, 0x6f, 0x95, 0xce, 0x5a, 0xab, 0x54, 0x68, 0xfb, 0x4b, 0x3b, - 0x9c, 0x0b, 0x68, 0x9d, 0x11, 0xc9, 0xa7, 0x84, 0xd1, 0x17, 0x64, 0x34, 0x41, 0x29, 0x11, 0x95, - 0x59, 0xbf, 0x63, 0xee, 0x17, 0x33, 0x55, 0xbd, 0xfc, 0xe0, 0xfc, 0x4a, 0x1e, 0x8e, 0xce, 0x9f, - 0xa8, 0xbd, 0x67, 0xe6, 0x1a, 0xca, 0xf1, 0xce, 0x6f, 0x16, 0xec, 0x0f, 0x47, 0xe7, 0x43, 0xfa, - 0x74, 0x4e, 0xf1, 0x48, 0x95, 0xf1, 0x0e, 0xa7, 0xd9, 0x9f, 0xc3, 0x4e, 0x21, 0x84, 0x36, 0x40, - 0x0d, 0xf8, 0x2a, 0xc7, 0xc7, 0x46, 0x16, 0xff, 0x6e, 0x2e, 0x90, 0xfd, 0x45, 0xf5, 0x5a, 0xaf, - 0xe9, 0x7d, 0xed, 0xb5, 0x7d, 0x85, 0x8d, 0x95, 0x2b, 0xdf, 0x79, 0x0a, 0x1f, 0x16, 0xf1, 0x4c, - 0x95, 0x27, 0x5c, 0xd7, 0x26, 0xbe, 0x9b, 0x93, 0xf4, 0x79, 0x21, 0xd1, 0x00, 0x9a, 0xb1, 0x48, - 0x82, 0x58, 0xf3, 0x0c, 0xf4, 0x99, 0xab, 0xec, 0x8a, 0x44, 0xcb, 0x7a, 0xf8, 0xfb, 0xb1, 0x48, - 0x2a, 0xdf, 0xce, 0x4b, 0x0b, 0x3a, 0x66, 0x78, 0xf3, 0x9c, 0xcb, 0xb9, 0x66, 0xd0, 0xa1, 0x8c, - 0x4a, 0x8a, 0xe2, 0xb2, 0x1d, 0x2b, 0x17, 0xc5, 0x0d, 0xe7, 0xb1, 0x6d, 0xce, 0x2c, 0xe8, 0x96, - 0x17, 0xc8, 0xc9, 0xf0, 0xd5, 0x55, 0xd7, 0x7a, 0x7d, 0xd5, 0xb5, 0xfe, 0xbe, 0xea, 0x5a, 0x2f, - 0xaf, 0xbb, 0x5b, 0xaf, 0xaf, 0xbb, 0x5b, 0x7f, 0x5c, 0x77, 0xb7, 0x2e, 0x8f, 0x2b, 0xa7, 0x8f, - 0x34, 0xcf, 0x87, 0x43, 0x14, 0x0a, 0xcf, 0xbc, 0xbd, 0x8b, 0xa3, 0xcf, 0xbc, 0x1f, 0xca, 0x17, - 0x58, 0x67, 0x0b, 0x6f, 0xeb, 0xe7, 0xf7, 0xd3, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x4b, 0x54, - 0xb4, 0x06, 0x48, 0x08, 0x00, 0x00, + // 840 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0x4f, 0x6f, 0x23, 0x35, + 0x14, 0xcf, 0x34, 0xab, 0xdd, 0x8d, 0x93, 0x36, 0xe9, 0x08, 0x2d, 0x69, 0x14, 0x25, 0x61, 0x16, + 0xc1, 0x0a, 0x69, 0x67, 0xd4, 0x82, 0x10, 0x88, 0xcb, 0xd2, 0x56, 0x68, 0x23, 0xa5, 0x48, 0x4c, + 0x5a, 0x0e, 0xbd, 0x8c, 0x3c, 0x63, 0x2b, 0xb1, 0x32, 0x63, 0xa7, 0x63, 0x27, 0xa5, 0xfd, 0x04, + 0x1c, 0x7b, 0xe5, 0x23, 0xc0, 0x85, 0x4f, 0xc0, 0x85, 0x53, 0x8f, 0x3d, 0x22, 0x0e, 0x05, 0xb5, + 0x5f, 0x04, 0xd9, 0xe3, 0xf9, 0x93, 0x04, 0x2a, 0x52, 0x38, 0x25, 0xf3, 0xfc, 0xb3, 0xdf, 0xfb, + 0xfd, 0x7e, 0x7e, 0xcf, 0xa0, 0xcb, 0x45, 0x4c, 0x10, 0x76, 0xb8, 0x80, 0x13, 0x4c, 0xfc, 0xc0, + 0x09, 0x60, 0x18, 0xfa, 0x30, 0x98, 0x70, 0x7b, 0x1a, 0x33, 0xc1, 0xcc, 0x7a, 0x02, 0xb0, 0x53, + 0x40, 0xeb, 0x9d, 0x11, 0x1b, 0x31, 0xb5, 0xe6, 0xc8, 0x7f, 0x09, 0xac, 0xd5, 0x09, 0x18, 0x8f, + 0x18, 0x77, 0x7c, 0xc8, 0xb1, 0x33, 0xdf, 0xf5, 0xb1, 0x80, 0xbb, 0x4e, 0xc0, 0x08, 0xd5, 0xeb, + 0x6d, 0x9d, 0x27, 0xc6, 0x01, 0x8b, 0x11, 0x4f, 0x7f, 0xf5, 0xea, 0x4a, 0x15, 0x63, 0xc6, 0x85, + 0x77, 0xc9, 0x28, 0xfe, 0x27, 0xc0, 0x1c, 0x86, 0x04, 0x41, 0xc1, 0xe2, 0x04, 0x60, 0x9d, 0x83, + 0xfa, 0x70, 0x1a, 0x12, 0x71, 0x88, 0x43, 0x3c, 0x82, 0x82, 0x30, 0x6a, 0xb6, 0x41, 0x25, 0x43, + 0x35, 0x8d, 0x9e, 0xf1, 0xaa, 0xe2, 0xe6, 0x01, 0xf3, 0x2b, 0xf0, 0x14, 0x46, 0x6c, 0x46, 0x45, + 0x73, 0x43, 0x2e, 0xed, 0xdb, 0xd7, 0xb7, 0xdd, 0xd2, 0xef, 0xb7, 0xdd, 0x0f, 0x46, 0x44, 0x8c, + 0x67, 0xbe, 0x1d, 0xb0, 0xc8, 0xd1, 0x9c, 0x92, 0x9f, 0xd7, 0x1c, 0x4d, 0x1c, 0x71, 0x31, 0xc5, + 0xdc, 0xee, 0x53, 0xe1, 0xea, 0xdd, 0xd6, 0xcf, 0x06, 0x68, 0xe8, 0xa4, 0xf8, 0x40, 0x6b, 0x67, + 0xf6, 0x40, 0x2d, 0x63, 0xe0, 0x11, 0xa4, 0xb3, 0x03, 0x19, 0x3b, 0x65, 0x14, 0xf7, 0x91, 0xf9, + 0x11, 0xd8, 0x46, 0x78, 0xca, 0x38, 0x11, 0x5e, 0x22, 0x85, 0x84, 0xc9, 0x4a, 0x9e, 0xb8, 0x75, + 0xbd, 0xe0, 0xaa, 0x78, 0x1f, 0x99, 0x47, 0x60, 0x9b, 0x4b, 0x6e, 0x1e, 0xca, 0xc8, 0xf1, 0x66, + 0xb9, 0x57, 0x7e, 0x55, 0xdd, 0xeb, 0xd9, 0x4b, 0xf6, 0xd8, 0x4b, 0x2a, 0xb8, 0x0d, 0xbe, 0x18, + 0xe0, 0xd6, 0xf7, 0x06, 0xd8, 0x3c, 0x08, 0x21, 0x89, 0xb2, 0x72, 0x3f, 0x07, 0x3b, 0x33, 0x8e, + 0x63, 0x2f, 0xc6, 0x08, 0x47, 0x53, 0x89, 0x2a, 0x14, 0x95, 0xd4, 0xfe, 0x42, 0x02, 0xdc, 0x6c, + 0x3d, 0xab, 0x6d, 0x07, 0x3c, 0x0f, 0xc6, 0x90, 0xd0, 0xb4, 0xfc, 0x8a, 0xfb, 0x4c, 0x7d, 0xf7, + 0x91, 0xf9, 0x1e, 0xa8, 0xe1, 0x29, 0x0b, 0xc6, 0x1e, 0x9d, 0x45, 0x3e, 0x8e, 0x9b, 0x65, 0xc5, + 0xae, 0xaa, 0x62, 0x5f, 0xab, 0x90, 0xf5, 0xa3, 0x01, 0x1a, 0x2e, 0x26, 0x74, 0x8e, 0xb9, 0xc8, + 0xaa, 0xe1, 0xa0, 0x1e, 0xeb, 0x98, 0xa7, 0x2d, 0x92, 0x35, 0x54, 0xf7, 0x76, 0xec, 0xc4, 0x09, + 0x5b, 0x5e, 0x32, 0x5b, 0x5f, 0x32, 0xfb, 0x80, 0x11, 0xba, 0xef, 0x48, 0xf7, 0x7e, 0xfa, 0xa3, + 0xfb, 0xe1, 0xbf, 0x70, 0x4f, 0x6e, 0x70, 0xb7, 0xd2, 0x14, 0x5f, 0xaa, 0x0c, 0x2b, 0x8e, 0x95, + 0x97, 0x1d, 0xb3, 0x7e, 0x35, 0x80, 0x79, 0x42, 0xd1, 0xfa, 0x56, 0xff, 0xad, 0x7d, 0x1b, 0x8f, + 0xb5, 0xcf, 0xfc, 0x02, 0xb4, 0x12, 0x59, 0x67, 0xd4, 0x67, 0x14, 0x11, 0x3a, 0xca, 0xcd, 0x4a, + 0xae, 0xc5, 0x13, 0xf7, 0x5d, 0x85, 0x38, 0x49, 0x01, 0xa9, 0x5b, 0x5c, 0x0a, 0xfe, 0x22, 0x27, + 0xf1, 0x96, 0x15, 0x64, 0x7f, 0x03, 0xca, 0x30, 0x4a, 0xa4, 0x5e, 0xbf, 0x1b, 0xe4, 0xd6, 0xff, + 0x99, 0xa8, 0xc5, 0x81, 0x99, 0x5f, 0xb8, 0x35, 0xf4, 0x7e, 0x58, 0xa0, 0x8d, 0x87, 0x05, 0xfa, + 0xc1, 0x00, 0x55, 0x17, 0xfb, 0x30, 0x84, 0x34, 0x20, 0x74, 0x64, 0xbe, 0x04, 0x9b, 0x3c, 0x0e, + 0xbc, 0xe5, 0x41, 0x52, 0xe3, 0x71, 0xf0, 0x6d, 0x36, 0x4b, 0x5e, 0x82, 0x4d, 0xc4, 0x45, 0x01, + 0x94, 0x74, 0x42, 0x0d, 0x71, 0x91, 0x83, 0xb4, 0xbe, 0xe5, 0x47, 0xeb, 0x6b, 0x9d, 0x83, 0xed, + 0xb4, 0xb4, 0x75, 0xee, 0xdf, 0x1b, 0x50, 0x8b, 0x73, 0x46, 0xa9, 0x23, 0xed, 0x15, 0x47, 0x0a, + 0xb4, 0xdd, 0x85, 0x1d, 0xd6, 0x09, 0x68, 0x1e, 0x62, 0xc1, 0x26, 0x98, 0x92, 0x4b, 0x3c, 0x1c, + 0xc3, 0x18, 0xf3, 0xc2, 0xec, 0x78, 0xa6, 0xe7, 0x95, 0xee, 0xd2, 0x6e, 0x7a, 0x70, 0x3a, 0xe2, + 0x07, 0xc3, 0xa3, 0x63, 0xb9, 0xf7, 0x50, 0x8f, 0xb5, 0x14, 0x6f, 0xfd, 0x62, 0x80, 0xad, 0xc1, + 0xf0, 0x68, 0x40, 0xce, 0x66, 0x04, 0x0d, 0x65, 0x19, 0xff, 0xe1, 0x34, 0xf3, 0x53, 0x50, 0xc9, + 0x84, 0x50, 0x06, 0xc8, 0x81, 0xb1, 0xcc, 0xf1, 0xad, 0x96, 0xc5, 0x7d, 0x9e, 0x0a, 0x64, 0x7e, + 0x56, 0x7c, 0x26, 0xca, 0x6a, 0x5f, 0x6b, 0x65, 0x5f, 0x66, 0x63, 0xe1, 0x09, 0xb1, 0xce, 0xc0, + 0xfb, 0x59, 0x3c, 0x51, 0xe5, 0x98, 0xa9, 0xda, 0xf8, 0x37, 0x33, 0x1c, 0x5f, 0x64, 0x12, 0xf5, + 0x41, 0x23, 0xe4, 0x91, 0x17, 0x2a, 0x9e, 0x9e, 0x3a, 0x73, 0x99, 0x5d, 0x96, 0x68, 0x51, 0x0f, + 0x77, 0x2b, 0xe4, 0x51, 0xe1, 0xdb, 0xba, 0x32, 0x40, 0x5b, 0xf7, 0x48, 0x9a, 0x73, 0x31, 0xd7, + 0x14, 0xb4, 0x09, 0x25, 0x82, 0xc0, 0x30, 0xbf, 0x8e, 0x85, 0x7e, 0x7c, 0x64, 0x7b, 0xb7, 0xf4, + 0x99, 0x19, 0xdd, 0xbc, 0x4f, 0xf7, 0x07, 0xd7, 0x77, 0x1d, 0xe3, 0xe6, 0xae, 0x63, 0xfc, 0x79, + 0xd7, 0x31, 0xae, 0xee, 0x3b, 0xa5, 0x9b, 0xfb, 0x4e, 0xe9, 0xb7, 0xfb, 0x4e, 0xe9, 0x74, 0xaf, + 0x70, 0xfa, 0x50, 0xf1, 0x7c, 0x3d, 0x80, 0x3e, 0x77, 0xf4, 0x5b, 0x3e, 0xdf, 0xfd, 0xc4, 0xf9, + 0x2e, 0x7f, 0xd1, 0x55, 0x36, 0xff, 0xa9, 0x7a, 0xce, 0x3f, 0xfe, 0x2b, 0x00, 0x00, 0xff, 0xff, + 0xe7, 0xf1, 0x50, 0xfb, 0x98, 0x08, 0x00, 0x00, } func (m *SplitDelegation) Marshal() (dAtA []byte, err error) { @@ -1011,6 +1019,20 @@ func (m *UndelegateHostCallback) MarshalToSizedBuffer(dAtA []byte) (int, error) _ = i var l int _ = l + if len(m.SplitDelegations) > 0 { + for iNdEx := len(m.SplitDelegations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SplitDelegations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCallbacks(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } { size := m.Amt.Size() i -= size @@ -1442,6 +1464,12 @@ func (m *UndelegateHostCallback) Size() (n int) { _ = l l = m.Amt.Size() n += 1 + l + sovCallbacks(uint64(l)) + if len(m.SplitDelegations) > 0 { + for _, e := range m.SplitDelegations { + l = e.Size() + n += 1 + l + sovCallbacks(uint64(l)) + } + } return n } @@ -2321,6 +2349,40 @@ func (m *UndelegateHostCallback) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SplitDelegations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCallbacks + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCallbacks + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCallbacks + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SplitDelegations = append(m.SplitDelegations, &SplitDelegation{}) + if err := m.SplitDelegations[len(m.SplitDelegations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipCallbacks(dAtA[iNdEx:]) From 20075fd507c02c7d9575fcf15bfe10a9219cb7c0 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 19:51:55 -0400 Subject: [PATCH 16/27] customise UpdateDelegationBalances copy for host (should update stakedBal too) --- x/stakeibc/keeper/icacallbacks_undelegate.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/x/stakeibc/keeper/icacallbacks_undelegate.go b/x/stakeibc/keeper/icacallbacks_undelegate.go index ef987edbfb..f11e608610 100644 --- a/x/stakeibc/keeper/icacallbacks_undelegate.go +++ b/x/stakeibc/keeper/icacallbacks_undelegate.go @@ -268,15 +268,15 @@ func (k Keeper) UndelegateHostCallback(ctx sdk.Context, packet channeltypes.Pack return errorsmod.Wrapf(types.ErrHostZoneNotFound, "host zone %s not found", EvmosHostZoneChainId) } + k.Logger(ctx).Info("UndelegateHostCallback success:", icacallbackstypes.AckResponseStatus_SUCCESS, packet) + // Update delegation balances - err := k.UpdateDelegationBalances(ctx, evmosHost, undelegateHostCallback) + err := k.UpdateDelegationBalancesHost(ctx, evmosHost, undelegateHostCallback) if err != nil { k.Logger(ctx).Error(fmt.Sprintf("UndelegateCallback | %s", err.Error())) return err } - k.Logger(ctx).Info("UndelegateHostCallback success:", icacallbackstypes.AckResponseStatus_SUCCESS, packet) - k.Logger(ctx).Info(">>>>>>>>>>> SetUndelegateHostPrevented <<<<<<<<<<<<<<<") if err := k.SetUndelegateHostPrevented(ctx); err != nil { return err @@ -285,11 +285,11 @@ func (k Keeper) UndelegateHostCallback(ctx sdk.Context, packet channeltypes.Pack return nil } -// Decrement the delegation field on the host zone and each validator's delegations after a successful unbonding ICA -func (k Keeper) UpdateDelegationBalances(ctx sdk.Context, hostZone types.HostZone, undelegateCallback types.UndelegateCallback) error { - // Undelegate from each validator and update host zone staked balance, if successful - for _, undelegation := range undelegateCallback.SplitDelegations { - err := k.AddDelegationToValidator(ctx, &hostZone, undelegation.Validator, undelegation.Amount.Neg(), ICACallbackID_Undelegate) +// Decrement the delegation field on host and each validator's delegations after a successful unbonding ICA +func (k Keeper) UpdateDelegationBalancesHost(ctx sdk.Context, hostZone types.HostZone, undelegateHostCallback types.UndelegateHostCallback) error { + // Undelegate from each validator and update Evmos staked balance, if successful + for _, undelegation := range undelegateHostCallback.SplitDelegations { + err := k.AddDelegationToValidator(ctx, &hostZone, undelegation.Validator, undelegation.Amount.Neg(), ICACallbackID_UndelegateHost) if err != nil { return err } From 64f52ad706fde2c4e60f0b059e8de9319c95663d Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 20:42:41 -0400 Subject: [PATCH 17/27] set MaxNumTokensUnbondableStr at 10m --- x/stakeibc/keeper/undelegate_host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stakeibc/keeper/undelegate_host.go b/x/stakeibc/keeper/undelegate_host.go index d85ed35c65..efd79e6024 100644 --- a/x/stakeibc/keeper/undelegate_host.go +++ b/x/stakeibc/keeper/undelegate_host.go @@ -14,7 +14,7 @@ import ( ) const ( - MaxNumTokensUnbondableStr = "1000000000000000000000000000" // 1e18 + MaxNumTokensUnbondableStr = "10000000000000000000000000" // 10,000,000e18 EvmosHostZoneChainId = "evmos_9001-2" ) From 9f2ca613ac3cf4b8b66612cbc25c87ba0173ab5b Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 21:47:56 -0400 Subject: [PATCH 18/27] DecrementValidatorDelegationChangesInProgress in callback --- x/stakeibc/keeper/icacallbacks_undelegate.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/x/stakeibc/keeper/icacallbacks_undelegate.go b/x/stakeibc/keeper/icacallbacks_undelegate.go index f11e608610..0d61610f58 100644 --- a/x/stakeibc/keeper/icacallbacks_undelegate.go +++ b/x/stakeibc/keeper/icacallbacks_undelegate.go @@ -250,6 +250,24 @@ func (k Keeper) UndelegateHostCallback(ctx sdk.Context, packet channeltypes.Pack } k.Logger(ctx).Info("Starting undelegate host callback for amount %v%s", undelegateHostCallback.Amt) + // Regardless of failure/success/timeout, indicate that this ICA has completed + hostZone, found := k.GetHostZone(ctx, EvmosHostZoneChainId) + if !found { + return errorsmod.Wrapf(sdkerrors.ErrKeyNotFound, "Host zone not found: %s", EvmosHostZoneChainId) + } + for _, splitDelegation := range undelegateHostCallback.SplitDelegations { + if err := k.DecrementValidatorDelegationChangesInProgress(&hostZone, splitDelegation.Validator); err != nil { + // TODO: Revert after v14 upgrade + if errors.Is(err, types.ErrInvalidValidatorDelegationUpdates) { + k.Logger(ctx).Error(utils.LogICACallbackWithHostZone(EvmosHostZoneChainId, ICACallbackID_Undelegate, + "Invariant failed - delegation changes in progress fell below 0 for %s", splitDelegation.Validator)) + continue + } + return err + } + } + k.SetHostZone(ctx, hostZone) + // Check for timeout (ack nil) if ackResponse.Status == icacallbackstypes.AckResponseStatus_TIMEOUT { k.Logger(ctx).Error("UndelegateHostCallback Timeout:", icacallbackstypes.AckResponseStatus_TIMEOUT, packet) From c6ff78f63c6cd2e4c77d7a106688557d971cbb23 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 21:48:09 -0400 Subject: [PATCH 19/27] unit test undelegatehostcallback --- .../keeper/icacallbacks_undelegate_test.go | 227 ++++++++++++++++++ 1 file changed, 227 insertions(+) diff --git a/x/stakeibc/keeper/icacallbacks_undelegate_test.go b/x/stakeibc/keeper/icacallbacks_undelegate_test.go index fac8def178..046ab07bc2 100644 --- a/x/stakeibc/keeper/icacallbacks_undelegate_test.go +++ b/x/stakeibc/keeper/icacallbacks_undelegate_test.go @@ -25,6 +25,16 @@ type UndelegateCallbackState struct { zoneAccountBalance sdkmath.Int } +type UndelegateCallbackHostState struct { + totalDelegations sdkmath.Int + val1Bal sdkmath.Int + val2Bal sdkmath.Int + epochNumber uint64 + completionTime time.Time + callbackArgs types.UndelegateHostCallback + zoneAccountBalance sdkmath.Int +} + type UndelegateCallbackArgs struct { packet channeltypes.Packet ackResponse *icacallbacktypes.AcknowledgementResponse @@ -39,6 +49,14 @@ type UndelegateCallbackTestCase struct { balanceToUnstake sdkmath.Int } +type UndelegateCallbackHostTestCase struct { + initialState UndelegateCallbackHostState + validArgs UndelegateCallbackArgs + val1UndelegationAmount sdkmath.Int + val2UndelegationAmount sdkmath.Int + balanceToUnstake sdkmath.Int +} + func (s *KeeperTestSuite) SetupUndelegateCallback() UndelegateCallbackTestCase { // Set up host zone and validator state totalDelegations := sdkmath.NewInt(1_000_000) @@ -142,6 +160,108 @@ func (s *KeeperTestSuite) SetupUndelegateCallback() UndelegateCallbackTestCase { } } +func (s *KeeperTestSuite) SetupUndelegateHostCallback() UndelegateCallbackHostTestCase { + // Set up host zone and validator state + totalDelegations := sdkmath.NewInt(1_000_000) + val1Bal := sdkmath.NewInt(400_000) + val2Bal := totalDelegations.Sub(val1Bal) + balanceToUnstake := sdkmath.NewInt(300_000) + val1UndelegationAmount := sdkmath.NewInt(120_000) + val2UndelegationAmount := balanceToUnstake.Sub(val1UndelegationAmount) + epochNumber := uint64(1) + val1 := types.Validator{ + Name: "val1", + Address: "val1_address", + Delegation: val1Bal, + DelegationChangesInProgress: 1, + } + val2 := types.Validator{ + Name: "val2", + Address: "val2_address", + Delegation: val2Bal, + DelegationChangesInProgress: 1, + } + depositAddress := types.NewHostZoneDepositAddress(HostChainId) + zoneAccountBalance := balanceToUnstake.Add(sdkmath.NewInt(10)) + zoneAccount := Account{ + acc: depositAddress, + stAtomBalance: sdk.NewCoin(StAtom, zoneAccountBalance), // Add a few extra tokens to make the test more robust + } + hostZone := types.HostZone{ + ChainId: HostChainId, + HostDenom: Atom, + IbcDenom: IbcAtom, + RedemptionRate: sdk.NewDec(1.0), + Validators: []*types.Validator{&val1, &val2}, + TotalDelegations: totalDelegations, + DepositAddress: depositAddress.String(), + } + s.App.StakeibcKeeper.SetHostZone(s.Ctx, hostZone) + + // Set up EpochUnbondingRecord, HostZoneUnbonding and token state + hostZoneUnbonding := recordtypes.HostZoneUnbonding{ + HostZoneId: HostChainId, + Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, + StTokenAmount: balanceToUnstake, + } + epochUnbondingRecord := recordtypes.EpochUnbondingRecord{ + EpochNumber: epochNumber, + HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{&hostZoneUnbonding}, + } + s.App.RecordsKeeper.SetEpochUnbondingRecord(s.Ctx, epochUnbondingRecord) + + // mint stTokens to the zone account, to be burned + s.FundAccount(zoneAccount.acc, zoneAccount.stAtomBalance) + + // Mock ack response + packet := channeltypes.Packet{} + completionTime := time.Now() + msgsUndelegateResponse := &stakingtypes.MsgUndelegateResponse{CompletionTime: completionTime} + msgsUndelegateResponseBz, err := proto.Marshal(msgsUndelegateResponse) + s.Require().NoError(err, "no error expected when marshalling undelegate response") + + ackResponse := icacallbacktypes.AcknowledgementResponse{ + Status: icacallbacktypes.AckResponseStatus_SUCCESS, + MsgResponses: [][]byte{msgsUndelegateResponseBz}, + } + + // Mock callback args + val1SplitDelegation := types.SplitDelegation{ + Validator: val1.Address, + Amount: val1UndelegationAmount, + } + val2SplitDelegation := types.SplitDelegation{ + Validator: val2.Address, + Amount: val2UndelegationAmount, + } + callbackArgs := types.UndelegateHostCallback{ + Amt: balanceToUnstake, + SplitDelegations: []*types.SplitDelegation{&val1SplitDelegation, &val2SplitDelegation}, + } + callbackArgsBz, err := proto.Marshal(&callbackArgs) + s.Require().NoError(err, "callback args unmarshalled") + + return UndelegateCallbackHostTestCase{ + val1UndelegationAmount: val1UndelegationAmount, + val2UndelegationAmount: val2UndelegationAmount, + balanceToUnstake: balanceToUnstake, + initialState: UndelegateCallbackHostState{ + callbackArgs: callbackArgs, + totalDelegations: totalDelegations, + val1Bal: val1Bal, + val2Bal: val2Bal, + epochNumber: epochNumber, + completionTime: completionTime, + zoneAccountBalance: zoneAccountBalance, + }, + validArgs: UndelegateCallbackArgs{ + packet: packet, + ackResponse: &ackResponse, + args: callbackArgsBz, + }, + } +} + func (s *KeeperTestSuite) TestUndelegateCallback_Successful() { tc := s.SetupUndelegateCallback() initialState := tc.initialState @@ -457,3 +577,110 @@ func (s *KeeperTestSuite) TestBurnTokens_CouldNotSendCoinsFromAccountToModule() err := s.App.StakeibcKeeper.BurnTokens(s.Ctx, hostZone, sdkmath.NewInt(123456)) s.Require().EqualError(err, "could not send coins from account stride1755g4dkhpw73gz9h9nwhlcefc6sdf8kcmvcwrk4rxfrz8xpxxjms7savm8 to module stakeibc. err: spendable balance is smaller than 123456stcoinDNE: insufficient funds") } + +func (s *KeeperTestSuite) TestUndelegateCallbackHost_Successful() { + tc := s.SetupUndelegateHostCallback() + initialState := tc.initialState + validArgs := tc.validArgs + + // Ensure IsUndelegateHostPrevented(ctx) is not yet flipped + s.Require().False(s.App.StakeibcKeeper.IsUndelegateHostPrevented(s.Ctx)) + + // Callback + err := s.App.StakeibcKeeper.UndelegateHostCallback(s.Ctx, validArgs.packet, validArgs.ackResponse, validArgs.args) + s.Require().NoError(err, "undelegate host callback succeeds") + + // Check that total delegation has decreased on the host zone + hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, HostChainId) + s.Require().True(found) + s.Require().Equal(hostZone.TotalDelegations, initialState.totalDelegations.Sub(tc.balanceToUnstake), "total delegation has decreased on the host zone") + + // Check that Delegations on validators have decreased + s.Require().True(len(hostZone.Validators) == 2, "Expected 2 validators") + val1 := hostZone.Validators[0] + val2 := hostZone.Validators[1] + s.Require().Equal(initialState.val1Bal.Sub(tc.val1UndelegationAmount), val1.Delegation, "val1 delegation has decreased") + s.Require().Equal(initialState.val2Bal.Sub(tc.val2UndelegationAmount), val2.Delegation, "val2 delegation has decreased") + + // Check that the number of delegation changes in progress was reset to 0 + s.Require().Equal(0, int(val1.DelegationChangesInProgress), "val1 delegation changes in progress") + s.Require().Equal(0, int(val2.DelegationChangesInProgress), "val2 delegation changes in progress") + + // ensure UndelegateHostPrevented has been flipped to true + s.Require().True(s.App.StakeibcKeeper.IsUndelegateHostPrevented(s.Ctx)) +} + +func (s *KeeperTestSuite) checkStateIfUndelegateCallbackHostFailed(tc UndelegateCallbackHostTestCase) { + initialState := tc.initialState + + // Check that total delegation has NOT decreased on the host zone + hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, HostChainId) + s.Require().True(found, "host zone found") + s.Require().Equal(initialState.totalDelegations, hostZone.TotalDelegations, "total delegation has NOT decreased on the host zone") + + // Check that Delegations on validators have NOT decreased + s.Require().True(len(hostZone.Validators) == 2, "Expected 2 validators") + val1 := hostZone.Validators[0] + val2 := hostZone.Validators[1] + s.Require().Equal(initialState.val1Bal, val1.Delegation, "val1 delegation has NOT decreased") + s.Require().Equal(initialState.val2Bal, val2.Delegation, "val2 delegation has NOT decreased") + + // Check that the number of delegation changes in progress was reset + s.Require().Equal(0, int(val1.DelegationChangesInProgress), "val1 delegation changes in progress") + s.Require().Equal(0, int(val2.DelegationChangesInProgress), "val2 delegation changes in progress") + + // Check that the host zone unbonding records have not been updated + epochUnbondingRecord, found := s.App.RecordsKeeper.GetEpochUnbondingRecord(s.Ctx, initialState.epochNumber) + s.Require().True(found, "epoch unbonding record found") + s.Require().Equal(len(epochUnbondingRecord.HostZoneUnbondings), 1, "1 host zone unbonding found") + hzu := epochUnbondingRecord.HostZoneUnbondings[0] + s.Require().Equal(int64(hzu.UnbondingTime), int64(0), "completion time is NOT set on the hzu") + s.Require().Equal(hzu.Status, recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, "hzu status is set to UNBONDING_QUEUE") + zoneAccount, err := sdk.AccAddressFromBech32(hostZone.DepositAddress) + s.Require().NoError(err, "zone account address is valid") + s.Require().Equal(initialState.zoneAccountBalance, s.App.BankKeeper.GetBalance(s.Ctx, zoneAccount, StAtom).Amount, "tokens are NOT burned") +} + +func (s *KeeperTestSuite) TestUndelegateCallbackHost_UndelegateCallbackTimeout() { + tc := s.SetupUndelegateHostCallback() + + // Update the ack response to indicate a timeout + invalidArgs := tc.validArgs + invalidArgs.ackResponse.Status = icacallbacktypes.AckResponseStatus_TIMEOUT + + err := s.App.StakeibcKeeper.UndelegateHostCallback(s.Ctx, invalidArgs.packet, invalidArgs.ackResponse, invalidArgs.args) + s.Require().NoError(err, "undelegate callback succeeds on timeout") + s.checkStateIfUndelegateCallbackHostFailed(tc) +} + +func (s *KeeperTestSuite) TestUndelegateCallbackHost_UndelegateCallbackErrorOnHost() { + tc := s.SetupUndelegateHostCallback() + + // an error ack means the tx failed on the host + invalidArgs := tc.validArgs + invalidArgs.ackResponse.Status = icacallbacktypes.AckResponseStatus_FAILURE + + err := s.App.StakeibcKeeper.UndelegateHostCallback(s.Ctx, invalidArgs.packet, invalidArgs.ackResponse, invalidArgs.args) + s.Require().NoError(err, "undelegate callback succeeds with error on host") + s.checkStateIfUndelegateCallbackHostFailed(tc) +} + +func (s *KeeperTestSuite) TestUndelegateCallbackHost_WrongCallbackArgs() { + tc := s.SetupUndelegateHostCallback() + + // random args should cause the callback to fail + invalidCallbackArgs := []byte("random bytes") + + err := s.App.StakeibcKeeper.UndelegateHostCallback(s.Ctx, tc.validArgs.packet, tc.validArgs.ackResponse, invalidCallbackArgs) + s.Require().EqualError(err, "Unable to unmarshal undelegate host callback args: unexpected EOF: unable to unmarshal data structure") +} + +func (s *KeeperTestSuite) TestUndelegateCallbackHost_HostNotFound() { + tc := s.SetupUndelegateHostCallback() + + // remove the host zone from the store to trigger a host not found error + s.App.StakeibcKeeper.RemoveHostZone(s.Ctx, HostChainId) + + err := s.App.StakeibcKeeper.UndelegateHostCallback(s.Ctx, tc.validArgs.packet, tc.validArgs.ackResponse, tc.validArgs.args) + s.Require().EqualError(err, "Host zone not found: GAIA: key not found") +} From ba55bc6312fbaf4bef481fe3317614b4418fb100 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 23:23:33 -0400 Subject: [PATCH 20/27] copy unbondhost test before customizing --- x/stakeibc/keeper/undelegate_host.go | 21 +- x/stakeibc/keeper/undelegate_host_test.go | 852 ++++++++++++++++++++++ 2 files changed, 862 insertions(+), 11 deletions(-) create mode 100644 x/stakeibc/keeper/undelegate_host_test.go diff --git a/x/stakeibc/keeper/undelegate_host.go b/x/stakeibc/keeper/undelegate_host.go index efd79e6024..71fc9d969b 100644 --- a/x/stakeibc/keeper/undelegate_host.go +++ b/x/stakeibc/keeper/undelegate_host.go @@ -22,6 +22,16 @@ const ( // The total unbond amount is input, capped at MaxNumTokensUnbondable. func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) error { + // if the total unbond amount is greater than the max, exit + MaxNumTokensUnbondable, found := math.NewIntFromString(MaxNumTokensUnbondableStr) + if !found { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "unable to parse MaxNumTokensUnbondable %s", MaxNumTokensUnbondable) + } + if totalUnbondAmount.GT(MaxNumTokensUnbondable) { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "total unbond amount %v is greater than MaxNumTokensUnbondable %v", + totalUnbondAmount, MaxNumTokensUnbondable) + } + // Get the host zone evmosHost, found := k.GetHostZone(ctx, EvmosHostZoneChainId) if !found { @@ -36,17 +46,6 @@ func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) return nil } - // if the total unbond amount is greater than the max, exit - // TODO: this overflows above ~100e18, NEED NEW TYPE - MaxNumTokensUnbondable, found := math.NewIntFromString(MaxNumTokensUnbondableStr) - if !found { - return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "unable to parse MaxNumTokensUnbondable %s", MaxNumTokensUnbondable) - } - if totalUnbondAmount.GT(MaxNumTokensUnbondable) { - return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "total unbond amount %v%s is greater than MaxNumTokensUnbondable %v%s", - totalUnbondAmount, evmosHost.HostDenom, MaxNumTokensUnbondable, evmosHost.HostDenom) - } - k.Logger(ctx).Info("Preparing MsgUndelegates from the delegation account to each validator on Evmos") // Confirm the delegation account was registered diff --git a/x/stakeibc/keeper/undelegate_host_test.go b/x/stakeibc/keeper/undelegate_host_test.go new file mode 100644 index 0000000000..aa65cdbe62 --- /dev/null +++ b/x/stakeibc/keeper/undelegate_host_test.go @@ -0,0 +1,852 @@ +package keeper_test + +import ( + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + _ "github.com/stretchr/testify/suite" + + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + epochstypes "github.com/Stride-Labs/stride/v14/x/epochs/types" + recordtypes "github.com/Stride-Labs/stride/v14/x/records/types" + "github.com/Stride-Labs/stride/v14/x/stakeibc/keeper" + "github.com/Stride-Labs/stride/v14/x/stakeibc/types" +) + +type ValidatorUnbonding struct { + Validator string + UnbondAmount sdkmath.Int +} + +type UnbondingTestCase struct { + hostZone types.HostZone + totalUnbondAmount sdkmath.Int + delegationChannelID string + delegationPortID string + channelStartSequence uint64 + expectedUnbondingRecordIds []uint64 +} + +func (s *KeeperTestSuite) SetupTestUnbondFromHostZone( + totalWeight int64, + totalStake sdkmath.Int, + unbondAmount sdkmath.Int, + validators []*types.Validator, +) UnbondingTestCase { + delegationAccountOwner := types.FormatICAAccountOwner(HostChainId, types.ICAAccountType_DELEGATION) + delegationChannelID, delegationPortID := s.CreateICAChannel(delegationAccountOwner) + + // Sanity checks: + // - total stake matches + // - total weights sum to 100 + actualTotalStake := sdkmath.ZeroInt() + actualTotalWeights := uint64(0) + for _, validator := range validators { + actualTotalStake = actualTotalStake.Add(validator.Delegation) + actualTotalWeights += validator.Weight + } + s.Require().Equal(totalStake.Int64(), actualTotalStake.Int64(), "test setup failed - total stake does not match") + s.Require().Equal(totalWeight, int64(actualTotalWeights), "test setup failed - total weight does not match") + + // Store the validators on the host zone + hostZone := types.HostZone{ + ChainId: HostChainId, + ConnectionId: ibctesting.FirstConnectionID, + HostDenom: Atom, + DelegationIcaAddress: "cosmos_DELEGATION", + Validators: validators, + TotalDelegations: totalStake, + } + s.App.StakeibcKeeper.SetHostZone(s.Ctx, hostZone) + + // Store the total unbond amount across two epoch unbonding records + halfUnbondAmount := unbondAmount.Quo(sdkmath.NewInt(2)) + for i := uint64(1); i <= 2; i++ { + s.App.RecordsKeeper.SetEpochUnbondingRecord(s.Ctx, recordtypes.EpochUnbondingRecord{ + EpochNumber: i, + HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{ + { + HostZoneId: HostChainId, + Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, + NativeTokenAmount: halfUnbondAmount, + }, + }, + }) + } + + // Mock the epoch tracker to timeout 90% through the epoch + strideEpochTracker := types.EpochTracker{ + EpochIdentifier: epochstypes.DAY_EPOCH, + Duration: 10_000_000_000, // 10 second epochs + NextEpochStartTime: uint64(s.Coordinator.CurrentTime.UnixNano() + 30_000_000_000), // dictates timeout + } + s.App.StakeibcKeeper.SetEpochTracker(s.Ctx, strideEpochTracker) + + // Get tx seq number before the ICA was submitted to check whether an ICA was submitted + startSequence, found := s.App.IBCKeeper.ChannelKeeper.GetNextSequenceSend(s.Ctx, delegationPortID, delegationChannelID) + s.Require().True(found, "sequence number not found before ica") + + return UnbondingTestCase{ + hostZone: hostZone, + totalUnbondAmount: unbondAmount, + delegationChannelID: delegationChannelID, + delegationPortID: delegationPortID, + channelStartSequence: startSequence, + expectedUnbondingRecordIds: []uint64{1, 2}, + } +} + +// Helper function to check that an undelegation ICA was submitted and that the callback data +// holds the expected unbondings for each validator +func (s *KeeperTestSuite) CheckUnbondingMessages(tc UnbondingTestCase, expectedUnbondings []ValidatorUnbonding) { + // Trigger unbonding + err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, tc.hostZone) + s.Require().NoError(err, "no error expected when calling unbond from host") + + // Check that sequence number incremented from a sent ICA + endSequence, found := s.App.IBCKeeper.ChannelKeeper.GetNextSequenceSend(s.Ctx, tc.delegationPortID, tc.delegationChannelID) + s.Require().True(found, "sequence number not found after ica") + s.Require().Equal(tc.channelStartSequence+1, endSequence, "sequence number should have incremented") + + // Check that callback data was stored + callbackData := s.App.IcacallbacksKeeper.GetAllCallbackData(s.Ctx) + s.Require().Len(callbackData, 1, "there should only be one callback data stored") + + // Check host zone and epoch unbonding record id's + var actualCallback types.UndelegateCallback + err = proto.Unmarshal(callbackData[0].CallbackArgs, &actualCallback) + s.Require().NoError(err, "no error expected when unmarshalling callback args") + + s.Require().Equal(HostChainId, actualCallback.HostZoneId, "chain-id on callback") + s.Require().Equal(tc.expectedUnbondingRecordIds, actualCallback.EpochUnbondingRecordIds, "unbonding record id's on callback") + + // Check splits from callback data align with expected unbondings + s.Require().Len(actualCallback.SplitDelegations, len(expectedUnbondings), "number of unbonding messages") + for i, expected := range expectedUnbondings { + actualSplit := actualCallback.SplitDelegations[i] + s.Require().Equal(expected.Validator, actualSplit.Validator, "callback message validator - index %d", i) + s.Require().Equal(expected.UnbondAmount.Int64(), actualSplit.Amount.Int64(), "callback message amount - index %d", i) + } + + // Check the delegation change in progress was incremented from each that had an unbonding + actualHostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, HostChainId) + s.Require().True(found, "host zone should have been found") + + for _, actualValidator := range actualHostZone.Validators { + validatorUnbonded := false + for _, unbondedVal := range expectedUnbondings { + if actualValidator.Address == unbondedVal.Validator { + validatorUnbonded = true + } + } + + expectedDelegationChangesInProgress := 0 + if validatorUnbonded { + expectedDelegationChangesInProgress = 1 + } + s.Require().Equal(expectedDelegationChangesInProgress, int(actualValidator.DelegationChangesInProgress), + "validator %s delegation changes in progress", actualValidator.Address) + } + + // Check that the unbond event was emitted with the proper unbond amount + s.CheckEventValueEmitted(types.EventTypeUndelegation, types.AttributeKeyTotalUnbondAmount, tc.totalUnbondAmount.String()) +} + +func (s *KeeperTestSuite) TestUnbondFromHostZone_Successful_UnbondOnlyZeroWeightVals() { + // Native Stake: 1000 + // LSM Stake: 250 + // Total Stake: 1250 + // + // Unbond Amount: 50 + // Stake After Unbond: 1200 + totalUnbondAmount := sdkmath.NewInt(50) + totalStake := sdkmath.NewInt(1250) + totalWeight := int64(100) + + validators := []*types.Validator{ + // Current: 100, Weight: 10%, Balanced: 10% * 1200 = 120, Capacity: 100-120 = -20 -> 0 + // No capacity -> unbondings + {Address: "valA", Weight: 10, Delegation: sdkmath.NewInt(100)}, + // Current: 420, Weight: 35%, Balanced: 35% * 1200 = 420, Capacity: 420-420 = 0 + // No capacity -> unbondings + {Address: "valB", Weight: 35, Delegation: sdkmath.NewInt(420)}, + // Weight: 0%, Balanced: 0, Capacity: 40 + // >>> Ratio: 0 -> Priority #1 <<< + {Address: "valC", Weight: 0, Delegation: sdkmath.NewInt(40)}, + // Current: 300, Weight: 30%, Balanced: 30% * 1200 = 360, Capacity: 300-360 = -60 -> 0 + // No capacity -> unbondings + {Address: "valD", Weight: 30, Delegation: sdkmath.NewInt(300)}, + // Weight: 0%, Balanced: 0, Capacity: 30 + // >>> Ratio: 0 -> Priority #2 <<< + {Address: "valE", Weight: 0, Delegation: sdkmath.NewInt(30)}, + // Current: 200, Weight: 10%, Balanced: 10% * 1200 = 120, Capacity: 200 - 120 = 80 + // >>> Ratio: 110/200 = 0.55 -> #3 Priority <<<< + {Address: "valF", Weight: 10, Delegation: sdkmath.NewInt(200)}, + // Current: 160, Weight: 15%, Balanced: 15% * 1200 = 180, Capacity: 160-180 = -20 -> 0 + // No capacity -> unbondings + {Address: "valG", Weight: 15, Delegation: sdkmath.NewInt(160)}, + } + + expectedUnbondings := []ValidatorUnbonding{ + // valC has #1 priority - unbond up to capacity at 40 + {Validator: "valC", UnbondAmount: sdkmath.NewInt(40)}, + // 50 - 40 = 10 unbond remaining + // valE has #2 priority - unbond up to remaining + {Validator: "valE", UnbondAmount: sdkmath.NewInt(10)}, + } + + tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) + s.CheckUnbondingMessages(tc, expectedUnbondings) +} + +func (s *KeeperTestSuite) TestUnbondFromHostZone_Successful_UnbondTotalLessThanTotalLSM() { + // Native Stake: 1000 + // LSM Stake: 250 + // Total Stake: 1250 + // + // Unbond Amount: 150 + // Stake After Unbond: 1100 + totalUnbondAmount := sdkmath.NewInt(150) + totalStake := sdkmath.NewInt(1250) + totalWeight := int64(100) + + validators := []*types.Validator{ + // Current: 100, Weight: 10%, Balanced: 10% * 1100 = 110, Capacity: 100-110 = -10 -> 0 + // No capacity -> unbondings + {Address: "valA", Weight: 10, Delegation: sdkmath.NewInt(100)}, + // Current: 420, Weight: 35%, Balanced: 35% * 1100 = 385, Capacity: 420-385 = 35 + // >>> Ratio: 385/420 = 0.91 -> Priority #4 <<< + {Address: "valB", Weight: 35, Delegation: sdkmath.NewInt(420)}, + // Weight: 0%, Balanced: 0, Capacity: 40 + // >>> Ratio: 0 -> Priority #1 <<< + {Address: "valC", Weight: 0, Delegation: sdkmath.NewInt(40)}, + // Current: 300, Weight: 30%, Balanced: 30% * 1100 = 330, Capacity: 300-330 = -30 -> 0 + // No capacity -> unbondings + {Address: "valD", Weight: 30, Delegation: sdkmath.NewInt(300)}, + // Weight: 0%, Balanced: 0, Capacity: 30 + // >>> Ratio: 0 -> Priority #2 <<< + {Address: "valE", Weight: 0, Delegation: sdkmath.NewInt(30)}, + // Current: 200, Weight: 10%, Balanced: 10% * 1100 = 110, Capacity: 200 - 110 = 90 + // >>> Ratio: 110/200 = 0.55 -> Priority #3 <<< + {Address: "valF", Weight: 10, Delegation: sdkmath.NewInt(200)}, + // Current: 160, Weight: 15%, Balanced: 15% * 1100 = 165, Capacity: 160-165 = -5 -> 0 + // No capacity -> unbondings + {Address: "valG", Weight: 15, Delegation: sdkmath.NewInt(160)}, + } + + expectedUnbondings := []ValidatorUnbonding{ + // valC has #1 priority - unbond up to capacity at 40 + {Validator: "valC", UnbondAmount: sdkmath.NewInt(40)}, + // 150 - 40 = 110 unbond remaining + // valE has #2 priority - unbond up to capacity at 30 + {Validator: "valE", UnbondAmount: sdkmath.NewInt(30)}, + // 150 - 40 - 30 = 80 unbond remaining + // valF has #3 priority - unbond up to remaining + {Validator: "valF", UnbondAmount: sdkmath.NewInt(80)}, + } + + tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) + s.CheckUnbondingMessages(tc, expectedUnbondings) +} + +func (s *KeeperTestSuite) TestUnbondFromHostZone_Successful_UnbondTotalGreaterThanTotalLSM() { + // Native Stake: 1000 + // LSM Stake: 250 + // Total Stake: 1250 + // + // Unbond Amount: 350 + // Stake After Unbond: 900 + totalUnbondAmount := sdkmath.NewInt(350) + totalStake := sdkmath.NewInt(1250) + totalWeight := int64(100) + + validators := []*types.Validator{ + // Current: 100, Weight: 10%, Balanced: 10% * 900 = 90, Capacity: 100-90 = 10 + // >>> Ratio: 90/100 = 0.9 -> Priority #7 <<< + {Address: "valA", Weight: 10, Delegation: sdkmath.NewInt(100)}, + // Current: 420, Weight: 35%, Balanced: 35% * 900 = 315, Capacity: 420-315 = 105 + // >>> Ratio: 315/420 = 0.75 -> Priority #4 <<< + {Address: "valB", Weight: 35, Delegation: sdkmath.NewInt(420)}, + // Weight: 0%, Balanced: 0, Capacity: 40 + // >>> Ratio: 0 -> Priority #1 <<< + {Address: "valC", Weight: 0, Delegation: sdkmath.NewInt(40)}, + // Current: 300, Weight: 30%, Balanced: 30% * 900 = 270, Capacity: 300-270 = 30 + // >>> Ratio: 270/300 = 0.9 -> Priority #6 <<< + {Address: "valD", Weight: 30, Delegation: sdkmath.NewInt(300)}, + // Weight: 0%, Balanced: 0, Capacity: 30 + // >>> Ratio: 0 -> Priority #2 <<< + {Address: "valE", Weight: 0, Delegation: sdkmath.NewInt(30)}, + // Current: 200, Weight: 10%, Balanced: 10% * 900 = 90, Capacity: 200 - 90 = 110 + // >>> Ratio: 90/200 = 0.45 -> Priority #3 <<< + {Address: "valF", Weight: 10, Delegation: sdkmath.NewInt(200)}, + // Current: 160, Weight: 15%, Balanced: 15% * 900 = 135, Capacity: 160-135 = 25 + // >>> Ratio: 135/160 = 0.85 -> Priority #5 <<< + {Address: "valG", Weight: 15, Delegation: sdkmath.NewInt(160)}, + } + + expectedUnbondings := []ValidatorUnbonding{ + // valC has #1 priority - unbond up to capacity at 40 + {Validator: "valC", UnbondAmount: sdkmath.NewInt(40)}, + // 350 - 40 = 310 unbond remaining + // valE has #2 priority - unbond up to capacity at 30 + {Validator: "valE", UnbondAmount: sdkmath.NewInt(30)}, + // 310 - 30 = 280 unbond remaining + // valF has #3 priority - unbond up to capacity at 110 + {Validator: "valF", UnbondAmount: sdkmath.NewInt(110)}, + // 280 - 110 = 170 unbond remaining + // valB has #4 priority - unbond up to capacity at 105 + {Validator: "valB", UnbondAmount: sdkmath.NewInt(105)}, + // 170 - 105 = 65 unbond remaining + // valG has #5 priority - unbond up to capacity at 25 + {Validator: "valG", UnbondAmount: sdkmath.NewInt(25)}, + // 65 - 25 = 40 unbond remaining + // valD has #6 priority - unbond up to capacity at 30 + {Validator: "valD", UnbondAmount: sdkmath.NewInt(30)}, + // 40 - 30 = 10 unbond remaining + // valA has #7 priority - unbond up to remaining + {Validator: "valA", UnbondAmount: sdkmath.NewInt(10)}, + } + + tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) + s.CheckUnbondingMessages(tc, expectedUnbondings) +} + +func (s *KeeperTestSuite) TestUnbondFromHostZone_NoDelegationAccount() { + // Call unbond on a host zone without a delegation account - it should error + invalidHostZone := types.HostZone{ + ChainId: HostChainId, + DelegationIcaAddress: "", + } + err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, invalidHostZone) + s.Require().ErrorContains(err, "no delegation account found for GAIA: ICA acccount not found on host zone") +} + +func (s *KeeperTestSuite) TestUnbondFromHostZone_ZeroUnbondAmount() { + totalWeight := int64(0) + totalStake := sdkmath.ZeroInt() + totalUnbondAmount := sdkmath.ZeroInt() + tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, []*types.Validator{}) + + // Call unbond - it should NOT error since the unbond amount was 0 - but it should short circuit + err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, tc.hostZone) + s.Require().Nil(err, "unbond should not have thrown an error - it should have simply ignored the host zone") + + // Confirm no ICAs were sent + endSequence, found := s.App.IBCKeeper.ChannelKeeper.GetNextSequenceSend(s.Ctx, tc.delegationPortID, tc.delegationChannelID) + s.Require().True(found, "sequence number not found after ica") + s.Require().Equal(tc.channelStartSequence, endSequence, "sequence number should stay the same since no messages were sent") +} + +func (s *KeeperTestSuite) TestUnbondFromHostZone_ZeroValidatorWeights() { + // Setup the test with all zero-weight validators + totalWeight := int64(0) + totalStake := sdkmath.NewInt(100) + totalUnbondAmount := sdkmath.NewInt(10) + validators := []*types.Validator{ + {Address: "valA", Weight: 0, Delegation: sdkmath.NewInt(25)}, + {Address: "valB", Weight: 0, Delegation: sdkmath.NewInt(50)}, + {Address: "valC", Weight: 0, Delegation: sdkmath.NewInt(25)}, + } + tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) + + // Call unbond - it should fail + err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, tc.hostZone) + s.Require().ErrorContains(err, "No non-zero validators found for host zone") +} + +func (s *KeeperTestSuite) TestUnbondFromHostZone_InsufficientDelegations() { + // Setup the test where the total unbond amount is greater than the current delegations + totalWeight := int64(100) + totalStake := sdkmath.NewInt(100) + totalUnbondAmount := sdkmath.NewInt(200) + validators := []*types.Validator{ + {Address: "valA", Weight: 25, Delegation: sdkmath.NewInt(25)}, + {Address: "valB", Weight: 50, Delegation: sdkmath.NewInt(50)}, + {Address: "valC", Weight: 25, Delegation: sdkmath.NewInt(25)}, + } + tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) + + // Call unbond - it should fail + err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, tc.hostZone) + s.Require().ErrorContains(err, "Cannot calculate target delegation if final amount is less than or equal to zero") +} + +func (s *KeeperTestSuite) TestUnbondFromHostZone_ICAFailed() { + // Validator setup here is arbitrary as long as the totals match + totalWeight := int64(100) + totalStake := sdkmath.NewInt(100) + totalUnbondAmount := sdkmath.NewInt(10) + validators := []*types.Validator{{Address: "valA", Weight: 100, Delegation: sdkmath.NewInt(100)}} + tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) + + // Remove the connection ID from the host zone so that the ICA fails + invalidHostZone := tc.hostZone + invalidHostZone.ConnectionId = "" + + err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, invalidHostZone) + s.Require().ErrorContains(err, "unable to submit unbonding ICA for GAIA") +} + +func (s *KeeperTestSuite) TestGetBalanceRatio() { + testCases := []struct { + unbondCapacity keeper.ValidatorUnbondCapacity + expectedRatio sdk.Dec + errorExpected bool + }{ + { + unbondCapacity: keeper.ValidatorUnbondCapacity{ + BalancedDelegation: sdkmath.NewInt(0), + CurrentDelegation: sdkmath.NewInt(100), + }, + expectedRatio: sdk.ZeroDec(), + errorExpected: false, + }, + { + unbondCapacity: keeper.ValidatorUnbondCapacity{ + BalancedDelegation: sdkmath.NewInt(25), + CurrentDelegation: sdkmath.NewInt(100), + }, + expectedRatio: sdk.MustNewDecFromStr("0.25"), + errorExpected: false, + }, + { + unbondCapacity: keeper.ValidatorUnbondCapacity{ + BalancedDelegation: sdkmath.NewInt(75), + CurrentDelegation: sdkmath.NewInt(100), + }, + expectedRatio: sdk.MustNewDecFromStr("0.75"), + errorExpected: false, + }, + { + unbondCapacity: keeper.ValidatorUnbondCapacity{ + BalancedDelegation: sdkmath.NewInt(150), + CurrentDelegation: sdkmath.NewInt(100), + }, + expectedRatio: sdk.MustNewDecFromStr("1.5"), + errorExpected: false, + }, + { + unbondCapacity: keeper.ValidatorUnbondCapacity{ + BalancedDelegation: sdkmath.NewInt(100), + CurrentDelegation: sdkmath.NewInt(0), + }, + errorExpected: true, + }, + } + for _, tc := range testCases { + balanceRatio, err := tc.unbondCapacity.GetBalanceRatio() + if tc.errorExpected { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().Equal(tc.expectedRatio.String(), balanceRatio.String()) + } + } +} + +func (s *KeeperTestSuite) TestGetTotalUnbondAmountAndRecordsIds() { + epochUnbondingRecords := []recordtypes.EpochUnbondingRecord{ + { + EpochNumber: uint64(1), + HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{ + { + // Summed + HostZoneId: HostChainId, + NativeTokenAmount: sdkmath.NewInt(1), + Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, + }, + { + // Different host zone + HostZoneId: OsmoChainId, + NativeTokenAmount: sdkmath.NewInt(2), + Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, + }, + }, + }, + { + EpochNumber: uint64(2), + HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{ + { + // Summed + HostZoneId: HostChainId, + NativeTokenAmount: sdkmath.NewInt(3), + Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, + }, + { + // Different host zone + HostZoneId: OsmoChainId, + NativeTokenAmount: sdkmath.NewInt(4), + Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, + }, + }, + }, + { + EpochNumber: uint64(3), + HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{ + { + // Different Status + HostZoneId: HostChainId, + NativeTokenAmount: sdkmath.NewInt(5), + Status: recordtypes.HostZoneUnbonding_UNBONDING_IN_PROGRESS, + }, + { + // Different Status + HostZoneId: OsmoChainId, + NativeTokenAmount: sdkmath.NewInt(6), + Status: recordtypes.HostZoneUnbonding_UNBONDING_IN_PROGRESS, + }, + }, + }, + { + EpochNumber: uint64(4), + HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{ + { + // Different Host and Status + HostZoneId: OsmoChainId, + NativeTokenAmount: sdkmath.NewInt(7), + Status: recordtypes.HostZoneUnbonding_CLAIMABLE, + }, + { + // Summed + HostZoneId: HostChainId, + NativeTokenAmount: sdkmath.NewInt(8), + Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, + }, + }, + }, + } + + for _, epochUnbondingRecord := range epochUnbondingRecords { + s.App.RecordsKeeper.SetEpochUnbondingRecord(s.Ctx, epochUnbondingRecord) + } + + expectedUnbondAmount := int64(1 + 3 + 8) + expectedRecordIds := []uint64{1, 2, 4} + + actualUnbondAmount, actualRecordIds := s.App.StakeibcKeeper.GetTotalUnbondAmountAndRecordsIds(s.Ctx, HostChainId) + s.Require().Equal(expectedUnbondAmount, actualUnbondAmount.Int64(), "unbonded amount") + s.Require().Equal(expectedRecordIds, actualRecordIds, "epoch unbonding record IDs") +} + +func (s *KeeperTestSuite) TestGetValidatorUnbondCapacity() { + // Start with the expected returned list of validator capacities + expectedUnbondCapacity := []keeper.ValidatorUnbondCapacity{ + { + ValidatorAddress: "valA", + CurrentDelegation: sdkmath.NewInt(50), + BalancedDelegation: sdkmath.NewInt(0), + Capacity: sdkmath.NewInt(50), + }, + { + ValidatorAddress: "valB", + CurrentDelegation: sdkmath.NewInt(200), + BalancedDelegation: sdkmath.NewInt(5), + Capacity: sdkmath.NewInt(195), + }, + { + ValidatorAddress: "valC", + CurrentDelegation: sdkmath.NewInt(1089), + BalancedDelegation: sdkmath.NewInt(1000), + Capacity: sdkmath.NewInt(89), + }, + } + + // Build list of input validators and map of balanced delegations from expected list + validators := []*types.Validator{} + balancedDelegations := map[string]sdkmath.Int{} + for _, validatorCapacity := range expectedUnbondCapacity { + validators = append(validators, &types.Validator{ + Address: validatorCapacity.ValidatorAddress, + Delegation: validatorCapacity.CurrentDelegation, + }) + balancedDelegations[validatorCapacity.ValidatorAddress] = validatorCapacity.BalancedDelegation + } + + // Add validators with no capacity - none of these should be in the returned list + deficits := []int64{0, 10, 50} + valAddresses := []string{"valD", "valE", "valF"} + for i, deficit := range deficits { + address := valAddresses[i] + + // the delegation amount is arbitrary here + // all that mattesr is that it's less than the balance delegation + currentDelegation := sdkmath.NewInt(50) + balancedDelegation := currentDelegation.Add(sdkmath.NewInt(deficit)) + + validators = append(validators, &types.Validator{ + Address: address, + Delegation: currentDelegation, + }) + balancedDelegations[address] = balancedDelegation + } + + // Check capacity matches expectations + actualUnbondCapacity := s.App.StakeibcKeeper.GetValidatorUnbondCapacity(s.Ctx, validators, balancedDelegations) + s.Require().Len(actualUnbondCapacity, len(expectedUnbondCapacity), "number of expected unbondings") + + for i, expected := range expectedUnbondCapacity { + address := expected.ValidatorAddress + actual := actualUnbondCapacity[i] + s.Require().Equal(expected.ValidatorAddress, actual.ValidatorAddress, "address for %s", address) + s.Require().Equal(expected.CurrentDelegation.Int64(), actual.CurrentDelegation.Int64(), "current for %s", address) + s.Require().Equal(expected.BalancedDelegation.Int64(), actual.BalancedDelegation.Int64(), "balanced for %s", address) + s.Require().Equal(expected.Capacity.Int64(), actual.Capacity.Int64(), "capacity for %s", address) + } +} + +func (s *KeeperTestSuite) TestSortUnbondingCapacityByPriority() { + // First we define what the ideal list will look like after sorting + expectedSortedCapacities := []keeper.ValidatorUnbondCapacity{ + // Zero-weight validator's + { + // (1) Ratio: 0, Capacity: 100 + ValidatorAddress: "valE", + BalancedDelegation: sdkmath.NewInt(0), + CurrentDelegation: sdkmath.NewInt(100), // ratio = 0/100 + Capacity: sdkmath.NewInt(100), + }, + { + // (2) Ratio: 0, Capacity: 25 + ValidatorAddress: "valC", + BalancedDelegation: sdkmath.NewInt(0), + CurrentDelegation: sdkmath.NewInt(25), // ratio = 0/25 + Capacity: sdkmath.NewInt(25), + }, + { + // (3) Ratio: 0, Capacity: 25 + // Same ratio and capacity as above but name is tie breaker + ValidatorAddress: "valD", + BalancedDelegation: sdkmath.NewInt(0), + CurrentDelegation: sdkmath.NewInt(25), // ratio = 0/25 + Capacity: sdkmath.NewInt(25), + }, + // Non-zero-weight validator's + { + // (4) Ratio: 0.1 + ValidatorAddress: "valB", + BalancedDelegation: sdkmath.NewInt(1), + CurrentDelegation: sdkmath.NewInt(10), // ratio = 1/10 + Capacity: sdkmath.NewInt(9), + }, + { + // (5) Ratio: 0.25 + ValidatorAddress: "valH", + BalancedDelegation: sdkmath.NewInt(250), + CurrentDelegation: sdkmath.NewInt(1000), // ratio = 250/1000 + Capacity: sdkmath.NewInt(750), + }, + { + // (6) Ratio: 0.5, Capacity: 100 + ValidatorAddress: "valF", + BalancedDelegation: sdkmath.NewInt(100), + CurrentDelegation: sdkmath.NewInt(200), // ratio = 100/200 + Capacity: sdkmath.NewInt(100), + }, + { + // (7) Ratio: 0.5, Capacity: 100 + // Same ratio and capacity as above - name is tie breaker + ValidatorAddress: "valI", + BalancedDelegation: sdkmath.NewInt(100), + CurrentDelegation: sdkmath.NewInt(200), // ratio = 100/200 + Capacity: sdkmath.NewInt(100), + }, + { + // (8) Ratio: 0.5, Capacity: 50 + // Same ratio as above but capacity is lower + ValidatorAddress: "valG", + BalancedDelegation: sdkmath.NewInt(50), + CurrentDelegation: sdkmath.NewInt(100), // ratio = 50/100 + Capacity: sdkmath.NewInt(50), + }, + { + // (9) Ratio: 0.6 + ValidatorAddress: "valA", + BalancedDelegation: sdkmath.NewInt(6), + CurrentDelegation: sdkmath.NewInt(10), // ratio = 6/10 + Capacity: sdkmath.NewInt(4), + }, + } + + // Define the shuffled ordering of the array above by just specifying + // the validator addresses an a randomized order + shuffledOrder := []string{ + "valA", + "valD", + "valG", + "valF", + "valE", + "valB", + "valH", + "valI", + "valC", + } + + // Use ordering above in combination with the data structures from the + // expected list to shuffle the expected list into a list that will be the + // input to this function + inputCapacities := []keeper.ValidatorUnbondCapacity{} + for _, shuffledValAddress := range shuffledOrder { + for _, capacity := range expectedSortedCapacities { + if capacity.ValidatorAddress == shuffledValAddress { + inputCapacities = append(inputCapacities, capacity) + } + } + } + + // Sort the list + actualSortedCapacities, err := keeper.SortUnbondingCapacityByPriority(inputCapacities) + s.Require().NoError(err) + s.Require().Len(actualSortedCapacities, len(expectedSortedCapacities), "number of capacities") + + // To make the error easier to understand, we first compare just the list of validator addresses + actualValidators := []string{} + for _, actual := range actualSortedCapacities { + actualValidators = append(actualValidators, actual.ValidatorAddress) + } + expectedValidators := []string{} + for _, expected := range expectedSortedCapacities { + expectedValidators = append(expectedValidators, expected.ValidatorAddress) + } + s.Require().Equal(expectedValidators, actualValidators, "validator order") + + // Then we'll do a sanity check on each field + // If the above passes and this fails, that likely means the test was setup improperly + for i, expected := range expectedSortedCapacities { + actual := actualSortedCapacities[i] + address := expected.ValidatorAddress + s.Require().Equal(expected.ValidatorAddress, actual.ValidatorAddress, "validator %d address", i+1) + s.Require().Equal(expected.BalancedDelegation, actual.BalancedDelegation, "validator %s balanced", address) + s.Require().Equal(expected.CurrentDelegation, actual.CurrentDelegation, "validator %s current", address) + s.Require().Equal(expected.Capacity, actual.Capacity, "validator %s capacity", address) + } +} + +func (s *KeeperTestSuite) TestGetUnbondingICAMessages() { + delegationAddress := "cosmos_DELEGATION" + + hostZone := types.HostZone{ + ChainId: HostChainId, + HostDenom: Atom, + DelegationIcaAddress: delegationAddress, + } + + validatorCapacities := []keeper.ValidatorUnbondCapacity{ + {ValidatorAddress: "val1", Capacity: sdkmath.NewInt(100)}, + {ValidatorAddress: "val2", Capacity: sdkmath.NewInt(200)}, + {ValidatorAddress: "val3", Capacity: sdkmath.NewInt(300)}, + {ValidatorAddress: "val4", Capacity: sdkmath.NewInt(400)}, + } + + testCases := []struct { + name string + totalUnbondAmount sdkmath.Int + expectedUnbondings []ValidatorUnbonding + expectedError string + }{ + { + name: "unbond val1 partially", + totalUnbondAmount: sdkmath.NewInt(50), + expectedUnbondings: []ValidatorUnbonding{ + {Validator: "val1", UnbondAmount: sdkmath.NewInt(50)}, + }, + }, + { + name: "unbond val1 fully", + totalUnbondAmount: sdkmath.NewInt(100), + expectedUnbondings: []ValidatorUnbonding{ + {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, + }, + }, + { + name: "unbond val1 fully and val2 partially", + totalUnbondAmount: sdkmath.NewInt(200), + expectedUnbondings: []ValidatorUnbonding{ + {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, + {Validator: "val2", UnbondAmount: sdkmath.NewInt(100)}, + }, + }, + { + name: "unbond val1 val2 fully", + totalUnbondAmount: sdkmath.NewInt(300), + expectedUnbondings: []ValidatorUnbonding{ + {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, + {Validator: "val2", UnbondAmount: sdkmath.NewInt(200)}, + }, + }, + { + name: "unbond val1 val2 fully and val3 partially", + totalUnbondAmount: sdkmath.NewInt(450), + expectedUnbondings: []ValidatorUnbonding{ + {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, + {Validator: "val2", UnbondAmount: sdkmath.NewInt(200)}, + {Validator: "val3", UnbondAmount: sdkmath.NewInt(150)}, + }, + }, + { + name: "unbond val1 val2 and val3 fully", + totalUnbondAmount: sdkmath.NewInt(600), + expectedUnbondings: []ValidatorUnbonding{ + {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, + {Validator: "val2", UnbondAmount: sdkmath.NewInt(200)}, + {Validator: "val3", UnbondAmount: sdkmath.NewInt(300)}, + }, + }, + { + name: "full unbonding", + totalUnbondAmount: sdkmath.NewInt(1000), + expectedUnbondings: []ValidatorUnbonding{ + {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, + {Validator: "val2", UnbondAmount: sdkmath.NewInt(200)}, + {Validator: "val3", UnbondAmount: sdkmath.NewInt(300)}, + {Validator: "val4", UnbondAmount: sdkmath.NewInt(400)}, + }, + }, + { + name: "insufficient delegation", + totalUnbondAmount: sdkmath.NewInt(1001), + expectedError: "unable to unbond full amount", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + // Get the unbonding ICA messages for the test case + actualMessages, actualSplits, actualError := s.App.StakeibcKeeper.GetUnbondingICAMessages( + hostZone, + tc.totalUnbondAmount, + validatorCapacities, + ) + + // If this is an error test case, check the error message + if tc.expectedError != "" { + s.Require().ErrorContains(actualError, tc.expectedError, "error expected") + return + } + + // For the success case, check the error number of unbondings + s.Require().NoError(actualError, "no error expected when unbonding %v", tc.totalUnbondAmount) + s.Require().Len(actualMessages, len(tc.expectedUnbondings), "number of undelegate messages") + s.Require().Len(actualSplits, len(tc.expectedUnbondings), "number of validator splits") + + // Check each unbonding + for i, expected := range tc.expectedUnbondings { + valAddress := expected.Validator + actualMsg := actualMessages[i].(*stakingtypes.MsgUndelegate) + actualSplit := actualSplits[i] + + // Check the ICA message + s.Require().Equal(valAddress, actualMsg.ValidatorAddress, "ica message validator") + s.Require().Equal(delegationAddress, actualMsg.DelegatorAddress, "ica message delegator for %s", valAddress) + s.Require().Equal(Atom, actualMsg.Amount.Denom, "ica message denom for %s", valAddress) + s.Require().Equal(expected.UnbondAmount.Int64(), actualMsg.Amount.Amount.Int64(), + "ica message amount for %s", valAddress) + + // Check the callback + s.Require().Equal(expected.Validator, actualSplit.Validator, "callback validator for %s", valAddress) + s.Require().Equal(expected.UnbondAmount.Int64(), actualSplit.Amount.Int64(), "callback amount %s", valAddress) + } + }) + } +} From 2a552104a35077e04686a387cf499afb2224c62a Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 23:24:23 -0400 Subject: [PATCH 21/27] undelegate host unit tests --- x/stakeibc/keeper/undelegate_host_test.go | 566 ++-------------------- 1 file changed, 39 insertions(+), 527 deletions(-) diff --git a/x/stakeibc/keeper/undelegate_host_test.go b/x/stakeibc/keeper/undelegate_host_test.go index aa65cdbe62..4f8cea048c 100644 --- a/x/stakeibc/keeper/undelegate_host_test.go +++ b/x/stakeibc/keeper/undelegate_host_test.go @@ -1,40 +1,28 @@ package keeper_test import ( + "fmt" + + "cosmossdk.io/math" sdkmath "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/gogoproto/proto" ibctesting "github.com/cosmos/ibc-go/v7/testing" _ "github.com/stretchr/testify/suite" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - epochstypes "github.com/Stride-Labs/stride/v14/x/epochs/types" recordtypes "github.com/Stride-Labs/stride/v14/x/records/types" - "github.com/Stride-Labs/stride/v14/x/stakeibc/keeper" "github.com/Stride-Labs/stride/v14/x/stakeibc/types" ) -type ValidatorUnbonding struct { - Validator string - UnbondAmount sdkmath.Int -} - -type UnbondingTestCase struct { - hostZone types.HostZone - totalUnbondAmount sdkmath.Int - delegationChannelID string - delegationPortID string - channelStartSequence uint64 - expectedUnbondingRecordIds []uint64 -} +const UndelegateHostZoneChainId = "evmos_9001-2" // the relevant zone for this test -func (s *KeeperTestSuite) SetupTestUnbondFromHostZone( +func (s *KeeperTestSuite) SetupTestUndelegateHost( totalWeight int64, totalStake sdkmath.Int, unbondAmount sdkmath.Int, validators []*types.Validator, ) UnbondingTestCase { + HostChainId := UndelegateHostZoneChainId delegationAccountOwner := types.FormatICAAccountOwner(HostChainId, types.ICAAccountType_DELEGATION) delegationChannelID, delegationPortID := s.CreateICAChannel(delegationAccountOwner) @@ -100,9 +88,13 @@ func (s *KeeperTestSuite) SetupTestUnbondFromHostZone( // Helper function to check that an undelegation ICA was submitted and that the callback data // holds the expected unbondings for each validator -func (s *KeeperTestSuite) CheckUnbondingMessages(tc UnbondingTestCase, expectedUnbondings []ValidatorUnbonding) { +func (s *KeeperTestSuite) CheckUndelegateHostMessages(tc UnbondingTestCase, expectedUnbondings []ValidatorUnbonding) { + + // Check that IsUndelegateHostPrevented(ctx) has not yet been flipped to true + s.Require().False(s.App.StakeibcKeeper.IsUndelegateHostPrevented(s.Ctx)) + // Trigger unbonding - err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, tc.hostZone) + err := s.App.StakeibcKeeper.UndelegateHostEvmos(s.Ctx, tc.totalUnbondAmount) s.Require().NoError(err, "no error expected when calling unbond from host") // Check that sequence number incremented from a sent ICA @@ -115,12 +107,11 @@ func (s *KeeperTestSuite) CheckUnbondingMessages(tc UnbondingTestCase, expectedU s.Require().Len(callbackData, 1, "there should only be one callback data stored") // Check host zone and epoch unbonding record id's - var actualCallback types.UndelegateCallback + var actualCallback types.UndelegateHostCallback err = proto.Unmarshal(callbackData[0].CallbackArgs, &actualCallback) s.Require().NoError(err, "no error expected when unmarshalling callback args") - s.Require().Equal(HostChainId, actualCallback.HostZoneId, "chain-id on callback") - s.Require().Equal(tc.expectedUnbondingRecordIds, actualCallback.EpochUnbondingRecordIds, "unbonding record id's on callback") + s.Require().Equal(tc.totalUnbondAmount, actualCallback.Amt, "amount on callback") // Check splits from callback data align with expected unbondings s.Require().Len(actualCallback.SplitDelegations, len(expectedUnbondings), "number of unbonding messages") @@ -154,7 +145,7 @@ func (s *KeeperTestSuite) CheckUnbondingMessages(tc UnbondingTestCase, expectedU s.CheckEventValueEmitted(types.EventTypeUndelegation, types.AttributeKeyTotalUnbondAmount, tc.totalUnbondAmount.String()) } -func (s *KeeperTestSuite) TestUnbondFromHostZone_Successful_UnbondOnlyZeroWeightVals() { +func (s *KeeperTestSuite) TestUndelegateHost_Successful_UnbondOnlyZeroWeightVals() { // Native Stake: 1000 // LSM Stake: 250 // Total Stake: 1250 @@ -197,11 +188,11 @@ func (s *KeeperTestSuite) TestUnbondFromHostZone_Successful_UnbondOnlyZeroWeight {Validator: "valE", UnbondAmount: sdkmath.NewInt(10)}, } - tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) - s.CheckUnbondingMessages(tc, expectedUnbondings) + tc := s.SetupTestUndelegateHost(totalWeight, totalStake, totalUnbondAmount, validators) + s.CheckUndelegateHostMessages(tc, expectedUnbondings) } -func (s *KeeperTestSuite) TestUnbondFromHostZone_Successful_UnbondTotalLessThanTotalLSM() { +func (s *KeeperTestSuite) TestUndelegateHost_Successful_UnbondTotalLessThanTotalLSM() { // Native Stake: 1000 // LSM Stake: 250 // Total Stake: 1250 @@ -247,11 +238,11 @@ func (s *KeeperTestSuite) TestUnbondFromHostZone_Successful_UnbondTotalLessThanT {Validator: "valF", UnbondAmount: sdkmath.NewInt(80)}, } - tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) - s.CheckUnbondingMessages(tc, expectedUnbondings) + tc := s.SetupTestUndelegateHost(totalWeight, totalStake, totalUnbondAmount, validators) + s.CheckUndelegateHostMessages(tc, expectedUnbondings) } -func (s *KeeperTestSuite) TestUnbondFromHostZone_Successful_UnbondTotalGreaterThanTotalLSM() { +func (s *KeeperTestSuite) TestUndelegateHost_Successful_UnbondTotalGreaterThanTotalLSM() { // Native Stake: 1000 // LSM Stake: 250 // Total Stake: 1250 @@ -309,28 +300,27 @@ func (s *KeeperTestSuite) TestUnbondFromHostZone_Successful_UnbondTotalGreaterTh {Validator: "valA", UnbondAmount: sdkmath.NewInt(10)}, } - tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) - s.CheckUnbondingMessages(tc, expectedUnbondings) + tc := s.SetupTestUndelegateHost(totalWeight, totalStake, totalUnbondAmount, validators) + s.CheckUndelegateHostMessages(tc, expectedUnbondings) } -func (s *KeeperTestSuite) TestUnbondFromHostZone_NoDelegationAccount() { - // Call unbond on a host zone without a delegation account - it should error - invalidHostZone := types.HostZone{ - ChainId: HostChainId, - DelegationIcaAddress: "", - } - err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, invalidHostZone) - s.Require().ErrorContains(err, "no delegation account found for GAIA: ICA acccount not found on host zone") +func (s *KeeperTestSuite) TestUndelegateHost_AmountTooLarge() { + // Call undelegateHost with an amount that is greater than the max amount, it should fail + const maxNumTokensUnbondableStr = "10000000000000000000000000" + maxNumTokensUnbondable, found := math.NewIntFromString(maxNumTokensUnbondableStr) + s.Require().True(found, "could not parse MaxNumTokensUnbondable") + err := s.App.StakeibcKeeper.UndelegateHostEvmos(s.Ctx, maxNumTokensUnbondable.Add(math.NewInt(1))) + s.Require().ErrorContains(err, fmt.Sprintf("total unbond amount %v is greater than MaxNumTokensUnbondable %v", maxNumTokensUnbondable.Add(math.NewInt(1)), maxNumTokensUnbondable)) } -func (s *KeeperTestSuite) TestUnbondFromHostZone_ZeroUnbondAmount() { +func (s *KeeperTestSuite) TestUndelegateHost_ZeroUnbondAmount() { totalWeight := int64(0) totalStake := sdkmath.ZeroInt() totalUnbondAmount := sdkmath.ZeroInt() - tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, []*types.Validator{}) + tc := s.SetupTestUndelegateHost(totalWeight, totalStake, totalUnbondAmount, []*types.Validator{}) // Call unbond - it should NOT error since the unbond amount was 0 - but it should short circuit - err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, tc.hostZone) + err := s.App.StakeibcKeeper.UndelegateHostEvmos(s.Ctx, totalUnbondAmount) s.Require().Nil(err, "unbond should not have thrown an error - it should have simply ignored the host zone") // Confirm no ICAs were sent @@ -339,7 +329,7 @@ func (s *KeeperTestSuite) TestUnbondFromHostZone_ZeroUnbondAmount() { s.Require().Equal(tc.channelStartSequence, endSequence, "sequence number should stay the same since no messages were sent") } -func (s *KeeperTestSuite) TestUnbondFromHostZone_ZeroValidatorWeights() { +func (s *KeeperTestSuite) TestUndelegateHost_ZeroValidatorWeights() { // Setup the test with all zero-weight validators totalWeight := int64(0) totalStake := sdkmath.NewInt(100) @@ -349,14 +339,14 @@ func (s *KeeperTestSuite) TestUnbondFromHostZone_ZeroValidatorWeights() { {Address: "valB", Weight: 0, Delegation: sdkmath.NewInt(50)}, {Address: "valC", Weight: 0, Delegation: sdkmath.NewInt(25)}, } - tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) + s.SetupTestUndelegateHost(totalWeight, totalStake, totalUnbondAmount, validators) // Call unbond - it should fail - err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, tc.hostZone) + err := s.App.StakeibcKeeper.UndelegateHostEvmos(s.Ctx, totalUnbondAmount) s.Require().ErrorContains(err, "No non-zero validators found for host zone") } -func (s *KeeperTestSuite) TestUnbondFromHostZone_InsufficientDelegations() { +func (s *KeeperTestSuite) TestUndelegateHost_InsufficientDelegations() { // Setup the test where the total unbond amount is greater than the current delegations totalWeight := int64(100) totalStake := sdkmath.NewInt(100) @@ -366,487 +356,9 @@ func (s *KeeperTestSuite) TestUnbondFromHostZone_InsufficientDelegations() { {Address: "valB", Weight: 50, Delegation: sdkmath.NewInt(50)}, {Address: "valC", Weight: 25, Delegation: sdkmath.NewInt(25)}, } - tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) + s.SetupTestUndelegateHost(totalWeight, totalStake, totalUnbondAmount, validators) // Call unbond - it should fail - err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, tc.hostZone) + err := s.App.StakeibcKeeper.UndelegateHostEvmos(s.Ctx, totalUnbondAmount) s.Require().ErrorContains(err, "Cannot calculate target delegation if final amount is less than or equal to zero") } - -func (s *KeeperTestSuite) TestUnbondFromHostZone_ICAFailed() { - // Validator setup here is arbitrary as long as the totals match - totalWeight := int64(100) - totalStake := sdkmath.NewInt(100) - totalUnbondAmount := sdkmath.NewInt(10) - validators := []*types.Validator{{Address: "valA", Weight: 100, Delegation: sdkmath.NewInt(100)}} - tc := s.SetupTestUnbondFromHostZone(totalWeight, totalStake, totalUnbondAmount, validators) - - // Remove the connection ID from the host zone so that the ICA fails - invalidHostZone := tc.hostZone - invalidHostZone.ConnectionId = "" - - err := s.App.StakeibcKeeper.UnbondFromHostZone(s.Ctx, invalidHostZone) - s.Require().ErrorContains(err, "unable to submit unbonding ICA for GAIA") -} - -func (s *KeeperTestSuite) TestGetBalanceRatio() { - testCases := []struct { - unbondCapacity keeper.ValidatorUnbondCapacity - expectedRatio sdk.Dec - errorExpected bool - }{ - { - unbondCapacity: keeper.ValidatorUnbondCapacity{ - BalancedDelegation: sdkmath.NewInt(0), - CurrentDelegation: sdkmath.NewInt(100), - }, - expectedRatio: sdk.ZeroDec(), - errorExpected: false, - }, - { - unbondCapacity: keeper.ValidatorUnbondCapacity{ - BalancedDelegation: sdkmath.NewInt(25), - CurrentDelegation: sdkmath.NewInt(100), - }, - expectedRatio: sdk.MustNewDecFromStr("0.25"), - errorExpected: false, - }, - { - unbondCapacity: keeper.ValidatorUnbondCapacity{ - BalancedDelegation: sdkmath.NewInt(75), - CurrentDelegation: sdkmath.NewInt(100), - }, - expectedRatio: sdk.MustNewDecFromStr("0.75"), - errorExpected: false, - }, - { - unbondCapacity: keeper.ValidatorUnbondCapacity{ - BalancedDelegation: sdkmath.NewInt(150), - CurrentDelegation: sdkmath.NewInt(100), - }, - expectedRatio: sdk.MustNewDecFromStr("1.5"), - errorExpected: false, - }, - { - unbondCapacity: keeper.ValidatorUnbondCapacity{ - BalancedDelegation: sdkmath.NewInt(100), - CurrentDelegation: sdkmath.NewInt(0), - }, - errorExpected: true, - }, - } - for _, tc := range testCases { - balanceRatio, err := tc.unbondCapacity.GetBalanceRatio() - if tc.errorExpected { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().Equal(tc.expectedRatio.String(), balanceRatio.String()) - } - } -} - -func (s *KeeperTestSuite) TestGetTotalUnbondAmountAndRecordsIds() { - epochUnbondingRecords := []recordtypes.EpochUnbondingRecord{ - { - EpochNumber: uint64(1), - HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{ - { - // Summed - HostZoneId: HostChainId, - NativeTokenAmount: sdkmath.NewInt(1), - Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, - }, - { - // Different host zone - HostZoneId: OsmoChainId, - NativeTokenAmount: sdkmath.NewInt(2), - Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, - }, - }, - }, - { - EpochNumber: uint64(2), - HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{ - { - // Summed - HostZoneId: HostChainId, - NativeTokenAmount: sdkmath.NewInt(3), - Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, - }, - { - // Different host zone - HostZoneId: OsmoChainId, - NativeTokenAmount: sdkmath.NewInt(4), - Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, - }, - }, - }, - { - EpochNumber: uint64(3), - HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{ - { - // Different Status - HostZoneId: HostChainId, - NativeTokenAmount: sdkmath.NewInt(5), - Status: recordtypes.HostZoneUnbonding_UNBONDING_IN_PROGRESS, - }, - { - // Different Status - HostZoneId: OsmoChainId, - NativeTokenAmount: sdkmath.NewInt(6), - Status: recordtypes.HostZoneUnbonding_UNBONDING_IN_PROGRESS, - }, - }, - }, - { - EpochNumber: uint64(4), - HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{ - { - // Different Host and Status - HostZoneId: OsmoChainId, - NativeTokenAmount: sdkmath.NewInt(7), - Status: recordtypes.HostZoneUnbonding_CLAIMABLE, - }, - { - // Summed - HostZoneId: HostChainId, - NativeTokenAmount: sdkmath.NewInt(8), - Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, - }, - }, - }, - } - - for _, epochUnbondingRecord := range epochUnbondingRecords { - s.App.RecordsKeeper.SetEpochUnbondingRecord(s.Ctx, epochUnbondingRecord) - } - - expectedUnbondAmount := int64(1 + 3 + 8) - expectedRecordIds := []uint64{1, 2, 4} - - actualUnbondAmount, actualRecordIds := s.App.StakeibcKeeper.GetTotalUnbondAmountAndRecordsIds(s.Ctx, HostChainId) - s.Require().Equal(expectedUnbondAmount, actualUnbondAmount.Int64(), "unbonded amount") - s.Require().Equal(expectedRecordIds, actualRecordIds, "epoch unbonding record IDs") -} - -func (s *KeeperTestSuite) TestGetValidatorUnbondCapacity() { - // Start with the expected returned list of validator capacities - expectedUnbondCapacity := []keeper.ValidatorUnbondCapacity{ - { - ValidatorAddress: "valA", - CurrentDelegation: sdkmath.NewInt(50), - BalancedDelegation: sdkmath.NewInt(0), - Capacity: sdkmath.NewInt(50), - }, - { - ValidatorAddress: "valB", - CurrentDelegation: sdkmath.NewInt(200), - BalancedDelegation: sdkmath.NewInt(5), - Capacity: sdkmath.NewInt(195), - }, - { - ValidatorAddress: "valC", - CurrentDelegation: sdkmath.NewInt(1089), - BalancedDelegation: sdkmath.NewInt(1000), - Capacity: sdkmath.NewInt(89), - }, - } - - // Build list of input validators and map of balanced delegations from expected list - validators := []*types.Validator{} - balancedDelegations := map[string]sdkmath.Int{} - for _, validatorCapacity := range expectedUnbondCapacity { - validators = append(validators, &types.Validator{ - Address: validatorCapacity.ValidatorAddress, - Delegation: validatorCapacity.CurrentDelegation, - }) - balancedDelegations[validatorCapacity.ValidatorAddress] = validatorCapacity.BalancedDelegation - } - - // Add validators with no capacity - none of these should be in the returned list - deficits := []int64{0, 10, 50} - valAddresses := []string{"valD", "valE", "valF"} - for i, deficit := range deficits { - address := valAddresses[i] - - // the delegation amount is arbitrary here - // all that mattesr is that it's less than the balance delegation - currentDelegation := sdkmath.NewInt(50) - balancedDelegation := currentDelegation.Add(sdkmath.NewInt(deficit)) - - validators = append(validators, &types.Validator{ - Address: address, - Delegation: currentDelegation, - }) - balancedDelegations[address] = balancedDelegation - } - - // Check capacity matches expectations - actualUnbondCapacity := s.App.StakeibcKeeper.GetValidatorUnbondCapacity(s.Ctx, validators, balancedDelegations) - s.Require().Len(actualUnbondCapacity, len(expectedUnbondCapacity), "number of expected unbondings") - - for i, expected := range expectedUnbondCapacity { - address := expected.ValidatorAddress - actual := actualUnbondCapacity[i] - s.Require().Equal(expected.ValidatorAddress, actual.ValidatorAddress, "address for %s", address) - s.Require().Equal(expected.CurrentDelegation.Int64(), actual.CurrentDelegation.Int64(), "current for %s", address) - s.Require().Equal(expected.BalancedDelegation.Int64(), actual.BalancedDelegation.Int64(), "balanced for %s", address) - s.Require().Equal(expected.Capacity.Int64(), actual.Capacity.Int64(), "capacity for %s", address) - } -} - -func (s *KeeperTestSuite) TestSortUnbondingCapacityByPriority() { - // First we define what the ideal list will look like after sorting - expectedSortedCapacities := []keeper.ValidatorUnbondCapacity{ - // Zero-weight validator's - { - // (1) Ratio: 0, Capacity: 100 - ValidatorAddress: "valE", - BalancedDelegation: sdkmath.NewInt(0), - CurrentDelegation: sdkmath.NewInt(100), // ratio = 0/100 - Capacity: sdkmath.NewInt(100), - }, - { - // (2) Ratio: 0, Capacity: 25 - ValidatorAddress: "valC", - BalancedDelegation: sdkmath.NewInt(0), - CurrentDelegation: sdkmath.NewInt(25), // ratio = 0/25 - Capacity: sdkmath.NewInt(25), - }, - { - // (3) Ratio: 0, Capacity: 25 - // Same ratio and capacity as above but name is tie breaker - ValidatorAddress: "valD", - BalancedDelegation: sdkmath.NewInt(0), - CurrentDelegation: sdkmath.NewInt(25), // ratio = 0/25 - Capacity: sdkmath.NewInt(25), - }, - // Non-zero-weight validator's - { - // (4) Ratio: 0.1 - ValidatorAddress: "valB", - BalancedDelegation: sdkmath.NewInt(1), - CurrentDelegation: sdkmath.NewInt(10), // ratio = 1/10 - Capacity: sdkmath.NewInt(9), - }, - { - // (5) Ratio: 0.25 - ValidatorAddress: "valH", - BalancedDelegation: sdkmath.NewInt(250), - CurrentDelegation: sdkmath.NewInt(1000), // ratio = 250/1000 - Capacity: sdkmath.NewInt(750), - }, - { - // (6) Ratio: 0.5, Capacity: 100 - ValidatorAddress: "valF", - BalancedDelegation: sdkmath.NewInt(100), - CurrentDelegation: sdkmath.NewInt(200), // ratio = 100/200 - Capacity: sdkmath.NewInt(100), - }, - { - // (7) Ratio: 0.5, Capacity: 100 - // Same ratio and capacity as above - name is tie breaker - ValidatorAddress: "valI", - BalancedDelegation: sdkmath.NewInt(100), - CurrentDelegation: sdkmath.NewInt(200), // ratio = 100/200 - Capacity: sdkmath.NewInt(100), - }, - { - // (8) Ratio: 0.5, Capacity: 50 - // Same ratio as above but capacity is lower - ValidatorAddress: "valG", - BalancedDelegation: sdkmath.NewInt(50), - CurrentDelegation: sdkmath.NewInt(100), // ratio = 50/100 - Capacity: sdkmath.NewInt(50), - }, - { - // (9) Ratio: 0.6 - ValidatorAddress: "valA", - BalancedDelegation: sdkmath.NewInt(6), - CurrentDelegation: sdkmath.NewInt(10), // ratio = 6/10 - Capacity: sdkmath.NewInt(4), - }, - } - - // Define the shuffled ordering of the array above by just specifying - // the validator addresses an a randomized order - shuffledOrder := []string{ - "valA", - "valD", - "valG", - "valF", - "valE", - "valB", - "valH", - "valI", - "valC", - } - - // Use ordering above in combination with the data structures from the - // expected list to shuffle the expected list into a list that will be the - // input to this function - inputCapacities := []keeper.ValidatorUnbondCapacity{} - for _, shuffledValAddress := range shuffledOrder { - for _, capacity := range expectedSortedCapacities { - if capacity.ValidatorAddress == shuffledValAddress { - inputCapacities = append(inputCapacities, capacity) - } - } - } - - // Sort the list - actualSortedCapacities, err := keeper.SortUnbondingCapacityByPriority(inputCapacities) - s.Require().NoError(err) - s.Require().Len(actualSortedCapacities, len(expectedSortedCapacities), "number of capacities") - - // To make the error easier to understand, we first compare just the list of validator addresses - actualValidators := []string{} - for _, actual := range actualSortedCapacities { - actualValidators = append(actualValidators, actual.ValidatorAddress) - } - expectedValidators := []string{} - for _, expected := range expectedSortedCapacities { - expectedValidators = append(expectedValidators, expected.ValidatorAddress) - } - s.Require().Equal(expectedValidators, actualValidators, "validator order") - - // Then we'll do a sanity check on each field - // If the above passes and this fails, that likely means the test was setup improperly - for i, expected := range expectedSortedCapacities { - actual := actualSortedCapacities[i] - address := expected.ValidatorAddress - s.Require().Equal(expected.ValidatorAddress, actual.ValidatorAddress, "validator %d address", i+1) - s.Require().Equal(expected.BalancedDelegation, actual.BalancedDelegation, "validator %s balanced", address) - s.Require().Equal(expected.CurrentDelegation, actual.CurrentDelegation, "validator %s current", address) - s.Require().Equal(expected.Capacity, actual.Capacity, "validator %s capacity", address) - } -} - -func (s *KeeperTestSuite) TestGetUnbondingICAMessages() { - delegationAddress := "cosmos_DELEGATION" - - hostZone := types.HostZone{ - ChainId: HostChainId, - HostDenom: Atom, - DelegationIcaAddress: delegationAddress, - } - - validatorCapacities := []keeper.ValidatorUnbondCapacity{ - {ValidatorAddress: "val1", Capacity: sdkmath.NewInt(100)}, - {ValidatorAddress: "val2", Capacity: sdkmath.NewInt(200)}, - {ValidatorAddress: "val3", Capacity: sdkmath.NewInt(300)}, - {ValidatorAddress: "val4", Capacity: sdkmath.NewInt(400)}, - } - - testCases := []struct { - name string - totalUnbondAmount sdkmath.Int - expectedUnbondings []ValidatorUnbonding - expectedError string - }{ - { - name: "unbond val1 partially", - totalUnbondAmount: sdkmath.NewInt(50), - expectedUnbondings: []ValidatorUnbonding{ - {Validator: "val1", UnbondAmount: sdkmath.NewInt(50)}, - }, - }, - { - name: "unbond val1 fully", - totalUnbondAmount: sdkmath.NewInt(100), - expectedUnbondings: []ValidatorUnbonding{ - {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, - }, - }, - { - name: "unbond val1 fully and val2 partially", - totalUnbondAmount: sdkmath.NewInt(200), - expectedUnbondings: []ValidatorUnbonding{ - {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, - {Validator: "val2", UnbondAmount: sdkmath.NewInt(100)}, - }, - }, - { - name: "unbond val1 val2 fully", - totalUnbondAmount: sdkmath.NewInt(300), - expectedUnbondings: []ValidatorUnbonding{ - {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, - {Validator: "val2", UnbondAmount: sdkmath.NewInt(200)}, - }, - }, - { - name: "unbond val1 val2 fully and val3 partially", - totalUnbondAmount: sdkmath.NewInt(450), - expectedUnbondings: []ValidatorUnbonding{ - {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, - {Validator: "val2", UnbondAmount: sdkmath.NewInt(200)}, - {Validator: "val3", UnbondAmount: sdkmath.NewInt(150)}, - }, - }, - { - name: "unbond val1 val2 and val3 fully", - totalUnbondAmount: sdkmath.NewInt(600), - expectedUnbondings: []ValidatorUnbonding{ - {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, - {Validator: "val2", UnbondAmount: sdkmath.NewInt(200)}, - {Validator: "val3", UnbondAmount: sdkmath.NewInt(300)}, - }, - }, - { - name: "full unbonding", - totalUnbondAmount: sdkmath.NewInt(1000), - expectedUnbondings: []ValidatorUnbonding{ - {Validator: "val1", UnbondAmount: sdkmath.NewInt(100)}, - {Validator: "val2", UnbondAmount: sdkmath.NewInt(200)}, - {Validator: "val3", UnbondAmount: sdkmath.NewInt(300)}, - {Validator: "val4", UnbondAmount: sdkmath.NewInt(400)}, - }, - }, - { - name: "insufficient delegation", - totalUnbondAmount: sdkmath.NewInt(1001), - expectedError: "unable to unbond full amount", - }, - } - - for _, tc := range testCases { - s.Run(tc.name, func() { - // Get the unbonding ICA messages for the test case - actualMessages, actualSplits, actualError := s.App.StakeibcKeeper.GetUnbondingICAMessages( - hostZone, - tc.totalUnbondAmount, - validatorCapacities, - ) - - // If this is an error test case, check the error message - if tc.expectedError != "" { - s.Require().ErrorContains(actualError, tc.expectedError, "error expected") - return - } - - // For the success case, check the error number of unbondings - s.Require().NoError(actualError, "no error expected when unbonding %v", tc.totalUnbondAmount) - s.Require().Len(actualMessages, len(tc.expectedUnbondings), "number of undelegate messages") - s.Require().Len(actualSplits, len(tc.expectedUnbondings), "number of validator splits") - - // Check each unbonding - for i, expected := range tc.expectedUnbondings { - valAddress := expected.Validator - actualMsg := actualMessages[i].(*stakingtypes.MsgUndelegate) - actualSplit := actualSplits[i] - - // Check the ICA message - s.Require().Equal(valAddress, actualMsg.ValidatorAddress, "ica message validator") - s.Require().Equal(delegationAddress, actualMsg.DelegatorAddress, "ica message delegator for %s", valAddress) - s.Require().Equal(Atom, actualMsg.Amount.Denom, "ica message denom for %s", valAddress) - s.Require().Equal(expected.UnbondAmount.Int64(), actualMsg.Amount.Amount.Int64(), - "ica message amount for %s", valAddress) - - // Check the callback - s.Require().Equal(expected.Validator, actualSplit.Validator, "callback validator for %s", valAddress) - s.Require().Equal(expected.UnbondAmount.Int64(), actualSplit.Amount.Int64(), "callback amount %s", valAddress) - } - }) - } -} From b6f4e4fca13c9d43b633c9b5b82bdd545d731569 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Sun, 17 Sep 2023 23:24:43 -0400 Subject: [PATCH 22/27] nit print fix --- x/stakeibc/keeper/msg_undelegate_host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stakeibc/keeper/msg_undelegate_host.go b/x/stakeibc/keeper/msg_undelegate_host.go index 61be4d1d2b..426671751e 100644 --- a/x/stakeibc/keeper/msg_undelegate_host.go +++ b/x/stakeibc/keeper/msg_undelegate_host.go @@ -26,7 +26,7 @@ func (k msgServer) UndelegateHost(goCtx context.Context, msg *types.MsgUndelegat } // log: issuing an undelegation to Evmos - k.Logger(ctx).Info(fmt.Sprintf("Issuing an undelegation to Evmos")) + k.Logger(ctx).Info("Issuing an undelegation to Evmos") return &types.MsgUndelegateHostResponse{}, nil } From 89dda99ba2486fd6890f5bca05c7094f2e6f0d88 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Mon, 18 Sep 2023 01:53:10 -0400 Subject: [PATCH 23/27] add kv unit test, nit cleanup, set max to 2.5mil --- x/stakeibc/keeper/icacallbacks_undelegate.go | 3 ++- x/stakeibc/keeper/msg_undelegate_host_test.go | 27 +++++++++++++++++++ x/stakeibc/keeper/undelegate_host.go | 14 +++++----- 3 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 x/stakeibc/keeper/msg_undelegate_host_test.go diff --git a/x/stakeibc/keeper/icacallbacks_undelegate.go b/x/stakeibc/keeper/icacallbacks_undelegate.go index 0d61610f58..b452293134 100644 --- a/x/stakeibc/keeper/icacallbacks_undelegate.go +++ b/x/stakeibc/keeper/icacallbacks_undelegate.go @@ -295,8 +295,9 @@ func (k Keeper) UndelegateHostCallback(ctx sdk.Context, packet channeltypes.Pack return err } - k.Logger(ctx).Info(">>>>>>>>>>> SetUndelegateHostPrevented <<<<<<<<<<<<<<<") + k.Logger(ctx).Info("UndelegateHostCallback: SetUndelegateHostPrevented") if err := k.SetUndelegateHostPrevented(ctx); err != nil { + k.Logger(ctx).Error(fmt.Sprintf("UndelegateHostCallback failed due to SetUndelegateHostPrevented | %s", err.Error())) return err } diff --git a/x/stakeibc/keeper/msg_undelegate_host_test.go b/x/stakeibc/keeper/msg_undelegate_host_test.go new file mode 100644 index 0000000000..5d6160481f --- /dev/null +++ b/x/stakeibc/keeper/msg_undelegate_host_test.go @@ -0,0 +1,27 @@ +package keeper_test + +import ( + _ "github.com/stretchr/testify/suite" + + stakeibctypes "github.com/Stride-Labs/stride/v14/x/stakeibc/types" +) + +type SetUndelegateHostPreventedTestCase struct { + validMsg stakeibctypes.MsgUndelegateHost +} + +func (s *KeeperTestSuite) TestEnableStrictUnbondingCap_CapNotSet() { + + // make sure StrictUnbondingCap is not set + s.Require().False(s.App.StakeibcKeeper.IsUndelegateHostPrevented(s.Ctx), "undelegate host prevented") +} + +func (s *KeeperTestSuite) TestEnableStrictUnbondingCap_CapSet() { + + // set undelegate Prevented + err := s.App.StakeibcKeeper.SetUndelegateHostPrevented(s.Ctx) + s.Require().NoError(err, "set undelegate host prevented") + + // make sure StrictUnbondingCap is set + s.Require().True(s.App.StakeibcKeeper.IsUndelegateHostPrevented(s.Ctx), "strict unbonding cap set to true") +} diff --git a/x/stakeibc/keeper/undelegate_host.go b/x/stakeibc/keeper/undelegate_host.go index 71fc9d969b..639624204f 100644 --- a/x/stakeibc/keeper/undelegate_host.go +++ b/x/stakeibc/keeper/undelegate_host.go @@ -14,7 +14,7 @@ import ( ) const ( - MaxNumTokensUnbondableStr = "10000000000000000000000000" // 10,000,000e18 + MaxNumTokensUnbondableStr = "2500000000000000000000000" // 2,500,000e18 EvmosHostZoneChainId = "evmos_9001-2" ) @@ -23,13 +23,13 @@ const ( func (k Keeper) UndelegateHostEvmos(ctx sdk.Context, totalUnbondAmount math.Int) error { // if the total unbond amount is greater than the max, exit - MaxNumTokensUnbondable, found := math.NewIntFromString(MaxNumTokensUnbondableStr) - if !found { - return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "unable to parse MaxNumTokensUnbondable %s", MaxNumTokensUnbondable) + maxNumTokensUnbondable, ok := math.NewIntFromString(MaxNumTokensUnbondableStr) + if !ok { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "unable to parse maxNumTokensUnbondable %s", maxNumTokensUnbondable) } - if totalUnbondAmount.GT(MaxNumTokensUnbondable) { - return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "total unbond amount %v is greater than MaxNumTokensUnbondable %v", - totalUnbondAmount, MaxNumTokensUnbondable) + if totalUnbondAmount.GT(maxNumTokensUnbondable) { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "total unbond amount %v is greater than maxNumTokensUnbondable %v", + totalUnbondAmount, maxNumTokensUnbondable) } // Get the host zone From 5261d125bfff4a05c856cec9db6c700ced3ca056 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Mon, 18 Sep 2023 01:55:02 -0400 Subject: [PATCH 24/27] cleanup unit test --- x/stakeibc/keeper/msg_undelegate_host_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/x/stakeibc/keeper/msg_undelegate_host_test.go b/x/stakeibc/keeper/msg_undelegate_host_test.go index 5d6160481f..3642c96f64 100644 --- a/x/stakeibc/keeper/msg_undelegate_host_test.go +++ b/x/stakeibc/keeper/msg_undelegate_host_test.go @@ -2,14 +2,8 @@ package keeper_test import ( _ "github.com/stretchr/testify/suite" - - stakeibctypes "github.com/Stride-Labs/stride/v14/x/stakeibc/types" ) -type SetUndelegateHostPreventedTestCase struct { - validMsg stakeibctypes.MsgUndelegateHost -} - func (s *KeeperTestSuite) TestEnableStrictUnbondingCap_CapNotSet() { // make sure StrictUnbondingCap is not set From 701b4528e08b977d77dc5a1e4e7e4c5c10e5ba55 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Mon, 18 Sep 2023 01:56:47 -0400 Subject: [PATCH 25/27] UndelegateICABatchSize 30 -> 32 --- x/stakeibc/keeper/unbonding_records.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stakeibc/keeper/unbonding_records.go b/x/stakeibc/keeper/unbonding_records.go index 21e6100ea7..fcbdda64c9 100644 --- a/x/stakeibc/keeper/unbonding_records.go +++ b/x/stakeibc/keeper/unbonding_records.go @@ -20,7 +20,7 @@ import ( ) const ( - UndelegateICABatchSize = 30 + UndelegateICABatchSize = 32 ) type ValidatorUnbondCapacity struct { From d49cd00f7faeed60542ff16e666e225a7ebf1626 Mon Sep 17 00:00:00 2001 From: Riley Edmunds Date: Mon, 18 Sep 2023 02:07:24 -0400 Subject: [PATCH 26/27] add missing return in handler --- x/stakeibc/handler.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/stakeibc/handler.go b/x/stakeibc/handler.go index 279ec630ff..809d604611 100644 --- a/x/stakeibc/handler.go +++ b/x/stakeibc/handler.go @@ -60,6 +60,7 @@ func NewMessageHandler(k keeper.Keeper) sdk.Handler { return sdk.WrapServiceResult(ctx, res, err) case *types.MsgUndelegateHost: res, err := msgServer.UndelegateHost(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) case *types.MsgCalibrateDelegation: res, err := msgServer.CalibrateDelegation(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) From 05b83ac660c36f5d0f066d57b2c04d52e9480431 Mon Sep 17 00:00:00 2001 From: sampocs Date: Mon, 18 Sep 2023 01:41:26 -0500 Subject: [PATCH 27/27] fixed unit tests --- .../keeper/icacallbacks_undelegate_test.go | 15 ++++++++------- x/stakeibc/keeper/undelegate_host_test.go | 18 ++++++++---------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/x/stakeibc/keeper/icacallbacks_undelegate_test.go b/x/stakeibc/keeper/icacallbacks_undelegate_test.go index 046ab07bc2..f281270a7c 100644 --- a/x/stakeibc/keeper/icacallbacks_undelegate_test.go +++ b/x/stakeibc/keeper/icacallbacks_undelegate_test.go @@ -12,6 +12,7 @@ import ( icacallbacktypes "github.com/Stride-Labs/stride/v14/x/icacallbacks/types" recordtypes "github.com/Stride-Labs/stride/v14/x/records/types" + stakeibckeeper "github.com/Stride-Labs/stride/v14/x/stakeibc/keeper" "github.com/Stride-Labs/stride/v14/x/stakeibc/types" ) @@ -181,14 +182,14 @@ func (s *KeeperTestSuite) SetupUndelegateHostCallback() UndelegateCallbackHostTe Delegation: val2Bal, DelegationChangesInProgress: 1, } - depositAddress := types.NewHostZoneDepositAddress(HostChainId) + depositAddress := types.NewHostZoneDepositAddress(stakeibckeeper.EvmosHostZoneChainId) zoneAccountBalance := balanceToUnstake.Add(sdkmath.NewInt(10)) zoneAccount := Account{ acc: depositAddress, stAtomBalance: sdk.NewCoin(StAtom, zoneAccountBalance), // Add a few extra tokens to make the test more robust } hostZone := types.HostZone{ - ChainId: HostChainId, + ChainId: stakeibckeeper.EvmosHostZoneChainId, HostDenom: Atom, IbcDenom: IbcAtom, RedemptionRate: sdk.NewDec(1.0), @@ -200,7 +201,7 @@ func (s *KeeperTestSuite) SetupUndelegateHostCallback() UndelegateCallbackHostTe // Set up EpochUnbondingRecord, HostZoneUnbonding and token state hostZoneUnbonding := recordtypes.HostZoneUnbonding{ - HostZoneId: HostChainId, + HostZoneId: stakeibckeeper.EvmosHostZoneChainId, Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, StTokenAmount: balanceToUnstake, } @@ -591,7 +592,7 @@ func (s *KeeperTestSuite) TestUndelegateCallbackHost_Successful() { s.Require().NoError(err, "undelegate host callback succeeds") // Check that total delegation has decreased on the host zone - hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, HostChainId) + hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, stakeibckeeper.EvmosHostZoneChainId) s.Require().True(found) s.Require().Equal(hostZone.TotalDelegations, initialState.totalDelegations.Sub(tc.balanceToUnstake), "total delegation has decreased on the host zone") @@ -614,7 +615,7 @@ func (s *KeeperTestSuite) checkStateIfUndelegateCallbackHostFailed(tc Undelegate initialState := tc.initialState // Check that total delegation has NOT decreased on the host zone - hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, HostChainId) + hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, stakeibckeeper.EvmosHostZoneChainId) s.Require().True(found, "host zone found") s.Require().Equal(initialState.totalDelegations, hostZone.TotalDelegations, "total delegation has NOT decreased on the host zone") @@ -679,8 +680,8 @@ func (s *KeeperTestSuite) TestUndelegateCallbackHost_HostNotFound() { tc := s.SetupUndelegateHostCallback() // remove the host zone from the store to trigger a host not found error - s.App.StakeibcKeeper.RemoveHostZone(s.Ctx, HostChainId) + s.App.StakeibcKeeper.RemoveHostZone(s.Ctx, stakeibckeeper.EvmosHostZoneChainId) err := s.App.StakeibcKeeper.UndelegateHostCallback(s.Ctx, tc.validArgs.packet, tc.validArgs.ackResponse, tc.validArgs.args) - s.Require().EqualError(err, "Host zone not found: GAIA: key not found") + s.Require().EqualError(err, "Host zone not found: evmos_9001-2: key not found") } diff --git a/x/stakeibc/keeper/undelegate_host_test.go b/x/stakeibc/keeper/undelegate_host_test.go index 4f8cea048c..1867242de8 100644 --- a/x/stakeibc/keeper/undelegate_host_test.go +++ b/x/stakeibc/keeper/undelegate_host_test.go @@ -22,8 +22,7 @@ func (s *KeeperTestSuite) SetupTestUndelegateHost( unbondAmount sdkmath.Int, validators []*types.Validator, ) UnbondingTestCase { - HostChainId := UndelegateHostZoneChainId - delegationAccountOwner := types.FormatICAAccountOwner(HostChainId, types.ICAAccountType_DELEGATION) + delegationAccountOwner := types.FormatICAAccountOwner(UndelegateHostZoneChainId, types.ICAAccountType_DELEGATION) delegationChannelID, delegationPortID := s.CreateICAChannel(delegationAccountOwner) // Sanity checks: @@ -40,7 +39,7 @@ func (s *KeeperTestSuite) SetupTestUndelegateHost( // Store the validators on the host zone hostZone := types.HostZone{ - ChainId: HostChainId, + ChainId: UndelegateHostZoneChainId, ConnectionId: ibctesting.FirstConnectionID, HostDenom: Atom, DelegationIcaAddress: "cosmos_DELEGATION", @@ -56,7 +55,7 @@ func (s *KeeperTestSuite) SetupTestUndelegateHost( EpochNumber: i, HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{ { - HostZoneId: HostChainId, + HostZoneId: UndelegateHostZoneChainId, Status: recordtypes.HostZoneUnbonding_UNBONDING_QUEUE, NativeTokenAmount: halfUnbondAmount, }, @@ -122,7 +121,7 @@ func (s *KeeperTestSuite) CheckUndelegateHostMessages(tc UnbondingTestCase, expe } // Check the delegation change in progress was incremented from each that had an unbonding - actualHostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, HostChainId) + actualHostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, UndelegateHostZoneChainId) s.Require().True(found, "host zone should have been found") for _, actualValidator := range actualHostZone.Validators { @@ -306,11 +305,10 @@ func (s *KeeperTestSuite) TestUndelegateHost_Successful_UnbondTotalGreaterThanTo func (s *KeeperTestSuite) TestUndelegateHost_AmountTooLarge() { // Call undelegateHost with an amount that is greater than the max amount, it should fail - const maxNumTokensUnbondableStr = "10000000000000000000000000" - maxNumTokensUnbondable, found := math.NewIntFromString(maxNumTokensUnbondableStr) - s.Require().True(found, "could not parse MaxNumTokensUnbondable") - err := s.App.StakeibcKeeper.UndelegateHostEvmos(s.Ctx, maxNumTokensUnbondable.Add(math.NewInt(1))) - s.Require().ErrorContains(err, fmt.Sprintf("total unbond amount %v is greater than MaxNumTokensUnbondable %v", maxNumTokensUnbondable.Add(math.NewInt(1)), maxNumTokensUnbondable)) + unbondAmount, ok := math.NewIntFromString("25000000000000000000000001") + s.Require().True(ok, "could not parse unbondAmount") + err := s.App.StakeibcKeeper.UndelegateHostEvmos(s.Ctx, unbondAmount) + s.Require().ErrorContains(err, fmt.Sprintf("total unbond amount %v is greater than", unbondAmount)) } func (s *KeeperTestSuite) TestUndelegateHost_ZeroUnbondAmount() {