diff --git a/proto/stride/stakeibc/callbacks.proto b/proto/stride/stakeibc/callbacks.proto index 11738336df..5656f6b1de 100644 --- a/proto/stride/stakeibc/callbacks.proto +++ b/proto/stride/stakeibc/callbacks.proto @@ -42,6 +42,14 @@ 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 + ]; + repeated SplitDelegation split_delegations = 2; +} + message RedemptionCallback { string host_zone_id = 1; repeated uint64 epoch_unbonding_record_ids = 2; diff --git a/proto/stride/stakeibc/tx.proto b/proto/stride/stakeibc/tx.proto index 0244edf150..6896faf553 100644 --- a/proto/stride/stakeibc/tx.proto +++ b/proto/stride/stakeibc/tx.proto @@ -30,6 +30,7 @@ service Msg { rpc CalibrateDelegation(MsgCalibrateDelegation) returns (MsgCalibrateDelegationResponse); rpc ClearBalance(MsgClearBalance) returns (MsgClearBalanceResponse); + rpc UndelegateHost(MsgUndelegateHost) returns (MsgUndelegateHostResponse); rpc UpdateInnerRedemptionRateBounds(MsgUpdateInnerRedemptionRateBounds) returns (MsgUpdateInnerRedemptionRateBoundsResponse); } @@ -172,6 +173,15 @@ 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 {} message MsgCalibrateDelegation { string creator = 1; diff --git a/x/stakeibc/client/cli/tx.go b/x/stakeibc/client/cli/tx.go index 3d29b21bad..eb78bb5340 100644 --- a/x/stakeibc/client/cli/tx.go +++ b/x/stakeibc/client/cli/tx.go @@ -37,6 +37,7 @@ func GetTxCmd() *cobra.Command { cmd.AddCommand(CmdUpdateValidatorSharesExchRate()) cmd.AddCommand(CmdCalibrateDelegation()) cmd.AddCommand(CmdClearBalance()) + cmd.AddCommand(CmdUndelegateHost()) cmd.AddCommand(CmdUpdateInnerRedemptionRateBounds()) 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/handler.go b/x/stakeibc/handler.go index 5bea7e9488..809d604611 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) case *types.MsgCalibrateDelegation: res, err := msgServer.CalibrateDelegation(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) 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)}, diff --git a/x/stakeibc/keeper/icacallbacks_undelegate.go b/x/stakeibc/keeper/icacallbacks_undelegate.go index 76e05938b1..b452293134 100644 --- a/x/stakeibc/keeper/icacallbacks_undelegate.go +++ b/x/stakeibc/keeper/icacallbacks_undelegate.go @@ -233,3 +233,86 @@ 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 SetUndelegateHostPrevented +// 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) + + // 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) + 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 + } + + // 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("UndelegateHostCallback success:", icacallbackstypes.AckResponseStatus_SUCCESS, packet) + + // Update delegation balances + 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: SetUndelegateHostPrevented") + if err := k.SetUndelegateHostPrevented(ctx); err != nil { + k.Logger(ctx).Error(fmt.Sprintf("UndelegateHostCallback failed due to SetUndelegateHostPrevented | %s", err.Error())) + return err + } + + return nil +} + +// 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 + } + } + k.SetHostZone(ctx, hostZone) + return nil +} diff --git a/x/stakeibc/keeper/icacallbacks_undelegate_test.go b/x/stakeibc/keeper/icacallbacks_undelegate_test.go index fac8def178..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" ) @@ -25,6 +26,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 +50,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 +161,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(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: stakeibckeeper.EvmosHostZoneChainId, + 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: stakeibckeeper.EvmosHostZoneChainId, + 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 +578,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, stakeibckeeper.EvmosHostZoneChainId) + 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, 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") + + // 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, 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: evmos_9001-2: key not found") +} diff --git a/x/stakeibc/keeper/msg_undelegate_host.go b/x/stakeibc/keeper/msg_undelegate_host.go new file mode 100644 index 0000000000..426671751e --- /dev/null +++ b/x/stakeibc/keeper/msg_undelegate_host.go @@ -0,0 +1,53 @@ +package keeper + +import ( + "context" + "fmt" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Stride-Labs/stride/v14/x/stakeibc/types" +) + +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 k.IsUndelegateHostPrevented(ctx) { + 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 { + return nil, fmt.Errorf("Error initiating host zone unbondings for UndelegateHostEvmos %s", err.Error()) + } + + // log: issuing an undelegation to Evmos + k.Logger(ctx).Info("Issuing an undelegation to Evmos") + + 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 +} 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..3642c96f64 --- /dev/null +++ b/x/stakeibc/keeper/msg_undelegate_host_test.go @@ -0,0 +1,21 @@ +package keeper_test + +import ( + _ "github.com/stretchr/testify/suite" +) + +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/unbonding_records.go b/x/stakeibc/keeper/unbonding_records.go index 0b76d4f5d9..d96222af13 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 { diff --git a/x/stakeibc/keeper/undelegate_host.go b/x/stakeibc/keeper/undelegate_host.go new file mode 100644 index 0000000000..639624204f --- /dev/null +++ b/x/stakeibc/keeper/undelegate_host.go @@ -0,0 +1,137 @@ +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 ( + MaxNumTokensUnbondableStr = "2500000000000000000000000" // 2,500,000e18 + EvmosHostZoneChainId = "evmos_9001-2" +) + +// 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 { + + // if the total unbond amount is greater than the max, exit + 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) + } + + // 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 + } + + 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 + undelegateHostCallback := types.UndelegateHostCallback{ + Amt: totalUnbondAmount, + SplitDelegations: unbondingsBatch, + } + callbackArgsBz, err := proto.Marshal(&undelegateHostCallback) + 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_UndelegateHost, + 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 +} diff --git a/x/stakeibc/keeper/undelegate_host_test.go b/x/stakeibc/keeper/undelegate_host_test.go new file mode 100644 index 0000000000..1867242de8 --- /dev/null +++ b/x/stakeibc/keeper/undelegate_host_test.go @@ -0,0 +1,362 @@ +package keeper_test + +import ( + "fmt" + + "cosmossdk.io/math" + sdkmath "cosmossdk.io/math" + "github.com/cosmos/gogoproto/proto" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + _ "github.com/stretchr/testify/suite" + + 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/types" +) + +const UndelegateHostZoneChainId = "evmos_9001-2" // the relevant zone for this test + +func (s *KeeperTestSuite) SetupTestUndelegateHost( + totalWeight int64, + totalStake sdkmath.Int, + unbondAmount sdkmath.Int, + validators []*types.Validator, +) UnbondingTestCase { + delegationAccountOwner := types.FormatICAAccountOwner(UndelegateHostZoneChainId, 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: UndelegateHostZoneChainId, + 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: UndelegateHostZoneChainId, + 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) 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.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 + 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.UndelegateHostCallback + err = proto.Unmarshal(callbackData[0].CallbackArgs, &actualCallback) + s.Require().NoError(err, "no error expected when unmarshalling callback args") + + 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") + 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, UndelegateHostZoneChainId) + 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) TestUndelegateHost_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.SetupTestUndelegateHost(totalWeight, totalStake, totalUnbondAmount, validators) + s.CheckUndelegateHostMessages(tc, expectedUnbondings) +} + +func (s *KeeperTestSuite) TestUndelegateHost_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.SetupTestUndelegateHost(totalWeight, totalStake, totalUnbondAmount, validators) + s.CheckUndelegateHostMessages(tc, expectedUnbondings) +} + +func (s *KeeperTestSuite) TestUndelegateHost_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.SetupTestUndelegateHost(totalWeight, totalStake, totalUnbondAmount, validators) + s.CheckUndelegateHostMessages(tc, expectedUnbondings) +} + +func (s *KeeperTestSuite) TestUndelegateHost_AmountTooLarge() { + // Call undelegateHost with an amount that is greater than the max amount, it should fail + 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() { + totalWeight := int64(0) + totalStake := sdkmath.ZeroInt() + totalUnbondAmount := sdkmath.ZeroInt() + 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.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 + 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) TestUndelegateHost_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)}, + } + s.SetupTestUndelegateHost(totalWeight, totalStake, totalUnbondAmount, validators) + + // Call unbond - it should fail + err := s.App.StakeibcKeeper.UndelegateHostEvmos(s.Ctx, totalUnbondAmount) + s.Require().ErrorContains(err, "No non-zero validators found for host zone") +} + +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) + 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)}, + } + s.SetupTestUndelegateHost(totalWeight, totalStake, totalUnbondAmount, validators) + + // Call unbond - it should fail + 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") +} diff --git a/x/stakeibc/types/callbacks.pb.go b/x/stakeibc/types/callbacks.pb.go index fd9999cd38..8d8b70cf94 100644 --- a/x/stakeibc/types/callbacks.pb.go +++ b/x/stakeibc/types/callbacks.pb.go @@ -303,6 +303,51 @@ 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"` + SplitDelegations []*SplitDelegation `protobuf:"bytes,2,rep,name=split_delegations,json=splitDelegations,proto3" json:"split_delegations,omitempty"` +} + +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 + +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"` @@ -312,7 +357,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 +410,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 +462,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 +513,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 +559,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 +617,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 +662,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 +697,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 +710,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, + // 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) { @@ -952,6 +999,53 @@ 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 + 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 + 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 +1456,23 @@ 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)) + if len(m.SplitDelegations) > 0 { + for _, e := range m.SplitDelegations { + l = e.Size() + n += 1 + l + sovCallbacks(uint64(l)) + } + } + return n +} + func (m *RedemptionCallback) Size() (n int) { if m == nil { return 0 @@ -2175,6 +2286,124 @@ 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 + 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:]) + 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 diff --git a/x/stakeibc/types/codec.go b/x/stakeibc/types/codec.go index c28fb0b674..71a00545b6 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) cdc.RegisterConcrete(&MsgCalibrateDelegation{}, "stakeibc/CalibrateDelegation", nil) cdc.RegisterConcrete(&MsgUpdateInnerRedemptionRateBounds{}, "stakeibc/UpdateInnerRedemptionRateBounds", nil) // this line is used by starport scaffolding # 2 @@ -41,6 +42,7 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { &MsgDeleteValidator{}, &MsgRestoreInterchainAccount{}, &MsgUpdateValidatorSharesExchRate{}, + &MsgUndelegateHost{}, &MsgCalibrateDelegation{}, &MsgUpdateInnerRedemptionRateBounds{}, ) diff --git a/x/stakeibc/types/errors.go b/x/stakeibc/types/errors.go index a0805b6f3f..1ab443f0a4 100644 --- a/x/stakeibc/types/errors.go +++ b/x/stakeibc/types/errors.go @@ -56,5 +56,6 @@ 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") - ErrInvalidBounds = errorsmod.Register(ModuleName, 1551, "Invalid safety bounds - inner bounds must be within outer bounds") + ErrUndelegateHostNotCallable = errorsmod.Register(ModuleName, 1551, "Undelegate host is disabled") + ErrInvalidBounds = errorsmod.Register(ModuleName, 1552, "Invalid safety bounds - inner bounds must be within outer bounds") ) diff --git a/x/stakeibc/types/message_undelegate_host.go b/x/stakeibc/types/message_undelegate_host.go new file mode 100644 index 0000000000..d239604cf8 --- /dev/null +++ b/x/stakeibc/types/message_undelegate_host.go @@ -0,0 +1,56 @@ +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 + } + if msg.Amount.IsZero() { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "amount must be positive") + } + return nil +} diff --git a/x/stakeibc/types/tx.pb.go b/x/stakeibc/types/tx.pb.go index 558a2b33d0..a89e0107ee 100644 --- a/x/stakeibc/types/tx.pb.go +++ b/x/stakeibc/types/tx.pb.go @@ -1278,6 +1278,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{26} +} +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{27} +} +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 + type MsgCalibrateDelegation struct { Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` @@ -1288,7 +1369,7 @@ func (m *MsgCalibrateDelegation) Reset() { *m = MsgCalibrateDelegation{} func (m *MsgCalibrateDelegation) String() string { return proto.CompactTextString(m) } func (*MsgCalibrateDelegation) ProtoMessage() {} func (*MsgCalibrateDelegation) Descriptor() ([]byte, []int) { - return fileDescriptor_9b7e09c9ad51cd54, []int{26} + return fileDescriptor_9b7e09c9ad51cd54, []int{28} } func (m *MsgCalibrateDelegation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1345,7 +1426,7 @@ func (m *MsgCalibrateDelegationResponse) Reset() { *m = MsgCalibrateDele func (m *MsgCalibrateDelegationResponse) String() string { return proto.CompactTextString(m) } func (*MsgCalibrateDelegationResponse) ProtoMessage() {} func (*MsgCalibrateDelegationResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_9b7e09c9ad51cd54, []int{27} + return fileDescriptor_9b7e09c9ad51cd54, []int{29} } func (m *MsgCalibrateDelegationResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1401,6 +1482,8 @@ 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") proto.RegisterType((*MsgCalibrateDelegation)(nil), "stride.stakeibc.MsgCalibrateDelegation") proto.RegisterType((*MsgCalibrateDelegationResponse)(nil), "stride.stakeibc.MsgCalibrateDelegationResponse") } @@ -1408,98 +1491,100 @@ func init() { func init() { proto.RegisterFile("stride/stakeibc/tx.proto", fileDescriptor_9b7e09c9ad51cd54) } var fileDescriptor_9b7e09c9ad51cd54 = []byte{ - // 1451 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcf, 0x6f, 0xdb, 0xc6, - 0x12, 0x36, 0x63, 0xc7, 0x51, 0xc6, 0xf2, 0x2f, 0xda, 0x71, 0x68, 0xe6, 0x45, 0x52, 0xe8, 0xf7, - 0x5e, 0xdd, 0x34, 0x96, 0x60, 0x3b, 0x40, 0xd1, 0xb4, 0x3d, 0x58, 0x76, 0x8a, 0x0a, 0x88, 0x82, - 0x82, 0x4e, 0x1a, 0x20, 0x40, 0xc1, 0xae, 0xc8, 0x0d, 0x45, 0x84, 0x5c, 0x2a, 0x5c, 0xca, 0x51, - 0x7a, 0x28, 0x7a, 0x29, 0xd0, 0x4b, 0x81, 0x16, 0x05, 0x7a, 0xe8, 0xa1, 0xc8, 0xa1, 0x87, 0x02, - 0xbd, 0x15, 0xf9, 0x23, 0x02, 0xf4, 0x12, 0xe4, 0x54, 0xf4, 0x20, 0x14, 0xc9, 0xa5, 0x67, 0xff, - 0x05, 0xc5, 0x2e, 0xa9, 0x95, 0x44, 0x51, 0x92, 0xe3, 0x18, 0x39, 0xd9, 0xbb, 0xf3, 0xed, 0xce, - 0xb7, 0xb3, 0x33, 0xdf, 0x8e, 0x08, 0x0a, 0x0d, 0x03, 0xc7, 0xc2, 0x25, 0x1a, 0xa2, 0xfb, 0xd8, - 0xa9, 0x99, 0xa5, 0xb0, 0x55, 0x6c, 0x04, 0x7e, 0xe8, 0xcb, 0xf3, 0x91, 0xa5, 0xd8, 0xb1, 0xa8, - 0x97, 0x92, 0x50, 0xc7, 0x44, 0x06, 0x32, 0x4d, 0xbf, 0x49, 0xc2, 0x68, 0x8d, 0x9a, 0x4f, 0x42, - 0x0e, 0x90, 0xeb, 0x58, 0x28, 0xf4, 0x83, 0x18, 0xb0, 0x6c, 0xfb, 0xb6, 0xcf, 0xff, 0x2d, 0xb1, - 0xff, 0xe2, 0xd9, 0x55, 0xd3, 0xa7, 0x9e, 0x4f, 0x8d, 0xc8, 0x10, 0x0d, 0x22, 0x93, 0xf6, 0xc7, - 0x29, 0xd0, 0xaa, 0xd4, 0xbe, 0xdd, 0xb0, 0x50, 0x88, 0x2b, 0x84, 0xe0, 0x40, 0xc7, 0x16, 0xf6, - 0x1a, 0xa1, 0xe3, 0x13, 0x1d, 0x85, 0xb8, 0xec, 0x37, 0x89, 0x45, 0x65, 0x05, 0xce, 0x98, 0x01, - 0x66, 0x8e, 0x14, 0xa9, 0x20, 0xad, 0x9f, 0xd5, 0x3b, 0x43, 0x79, 0x15, 0x32, 0x66, 0x1d, 0x39, - 0xc4, 0x70, 0x2c, 0xe5, 0x54, 0x6c, 0x62, 0xe3, 0x8a, 0x25, 0x3f, 0x84, 0x55, 0x8f, 0x19, 0xd8, - 0xae, 0x46, 0x20, 0xb6, 0x35, 0x02, 0x14, 0x62, 0x65, 0x92, 0x61, 0xcb, 0x1f, 0x3c, 0x6d, 0xe7, - 0x27, 0xfe, 0x6a, 0xe7, 0xff, 0x6f, 0x3b, 0x61, 0xbd, 0x59, 0x2b, 0x9a, 0xbe, 0x17, 0xf3, 0x8b, - 0xff, 0x6c, 0x50, 0xeb, 0x7e, 0x29, 0x7c, 0xd4, 0xc0, 0xb4, 0xb8, 0x87, 0xcd, 0xe7, 0x4f, 0x36, - 0x20, 0xa6, 0xbf, 0x87, 0x4d, 0x7d, 0xc5, 0x73, 0x48, 0x0a, 0x67, 0xee, 0x18, 0xb5, 0x86, 0x38, - 0x9e, 0x3a, 0x11, 0xc7, 0xa8, 0x95, 0xe2, 0x58, 0xbb, 0x02, 0x97, 0xc7, 0x07, 0x53, 0xc7, 0xb4, - 0xe1, 0x13, 0x8a, 0xb5, 0xef, 0x25, 0x98, 0xab, 0x52, 0xfb, 0x86, 0xf3, 0xa0, 0xe9, 0x58, 0xfb, - 0xec, 0x4a, 0x47, 0xc4, 0xf9, 0x23, 0x98, 0x46, 0x1e, 0x4b, 0x85, 0x28, 0xca, 0xe5, 0xe2, 0x2b, - 0x1c, 0xa0, 0x42, 0x42, 0x3d, 0x5e, 0x2d, 0x5f, 0x04, 0xa8, 0xfb, 0x34, 0x34, 0x2c, 0x4c, 0x7c, - 0x2f, 0xba, 0x05, 0xfd, 0x2c, 0x9b, 0xd9, 0x63, 0x13, 0x9a, 0x02, 0x2b, 0xfd, 0x94, 0x04, 0xdb, - 0x5f, 0x24, 0x58, 0x64, 0xa6, 0xfd, 0xea, 0x9b, 0x25, 0xbc, 0x01, 0x4b, 0x2e, 0xf5, 0x8c, 0xd0, - 0xbf, 0x8f, 0x89, 0xe1, 0xd4, 0xcc, 0x3e, 0xe6, 0x0b, 0x2e, 0xf5, 0x6e, 0x31, 0x4b, 0xa5, 0x66, - 0x46, 0x07, 0xb8, 0x09, 0xab, 0x03, 0x2c, 0x3b, 0x67, 0x90, 0x37, 0x61, 0x39, 0x0c, 0x10, 0xa1, - 0xc8, 0xe4, 0xf9, 0x60, 0xfa, 0x5e, 0xc3, 0xc5, 0x21, 0xe6, 0xd4, 0x33, 0xfa, 0x52, 0x8f, 0x6d, - 0x37, 0x36, 0x69, 0xbf, 0x4a, 0x30, 0x5f, 0xa5, 0xf6, 0xae, 0x8b, 0x51, 0x50, 0x46, 0x2e, 0x22, - 0x26, 0x3e, 0x5e, 0x35, 0x74, 0xe3, 0x31, 0xf9, 0x5a, 0xf1, 0x60, 0xce, 0xeb, 0x88, 0x10, 0xec, - 0x46, 0xa9, 0xac, 0x77, 0x86, 0xda, 0x2a, 0x9c, 0x4f, 0x30, 0x15, 0x97, 0xf7, 0x5b, 0x94, 0x6a, - 0x2c, 0x1d, 0xb1, 0xf7, 0xa6, 0x6e, 0xee, 0x02, 0xf0, 0xc4, 0x32, 0xbe, 0xf0, 0x49, 0x5c, 0xef, - 0x7a, 0x86, 0x4d, 0xdc, 0xf5, 0x09, 0x96, 0x55, 0xc8, 0x04, 0xd8, 0xc4, 0xce, 0x01, 0x0e, 0xe2, - 0x73, 0x88, 0x71, 0x9c, 0x84, 0x3d, 0x64, 0xc5, 0x39, 0x7e, 0x3f, 0x0d, 0x4b, 0xdc, 0x64, 0x3b, - 0x34, 0xc4, 0xc1, 0xc7, 0x9d, 0xdd, 0x3e, 0x84, 0x59, 0xd3, 0x27, 0x04, 0x47, 0xf7, 0xda, 0x09, - 0x7e, 0x59, 0x39, 0x6c, 0xe7, 0x97, 0x1f, 0x21, 0xcf, 0xbd, 0xa6, 0xf5, 0x99, 0x35, 0x3d, 0xdb, - 0x1d, 0x57, 0x2c, 0x59, 0x83, 0x6c, 0x0d, 0x9b, 0xf5, 0xed, 0xad, 0x46, 0x80, 0xef, 0x39, 0x2d, - 0x25, 0xcb, 0x09, 0xf5, 0xcd, 0xc9, 0x57, 0xfb, 0x0a, 0x27, 0x52, 0x91, 0x73, 0x87, 0xed, 0xfc, - 0x62, 0xb4, 0x7f, 0xd7, 0xa6, 0xf5, 0xd4, 0x93, 0xbc, 0x09, 0x67, 0xbb, 0x39, 0x7b, 0x9a, 0x2f, - 0x5a, 0x3e, 0x6c, 0xe7, 0x17, 0xa2, 0x45, 0xc2, 0xa4, 0xe9, 0x19, 0x27, 0xce, 0xe0, 0xde, 0x8b, - 0x99, 0xee, 0xbf, 0x98, 0x9b, 0x10, 0xa5, 0xe8, 0x3d, 0x1c, 0x18, 0xf1, 0xa5, 0xb3, 0xb3, 0x02, - 0xdf, 0x36, 0x77, 0xd8, 0xce, 0xab, 0xd1, 0xb6, 0x29, 0x20, 0x4d, 0x5f, 0xec, 0xcc, 0xee, 0x46, - 0x93, 0x3c, 0x25, 0x17, 0x9a, 0xa4, 0xe6, 0x13, 0xcb, 0x21, 0xb6, 0xd1, 0xc0, 0x81, 0xe3, 0x5b, - 0xca, 0x4c, 0x41, 0x5a, 0x9f, 0x2a, 0x5f, 0x38, 0x6c, 0xe7, 0xcf, 0x47, 0x9b, 0x25, 0x11, 0x9a, - 0x3e, 0x2f, 0xa6, 0x3e, 0xe1, 0x33, 0xb2, 0x0b, 0x4b, 0x4c, 0xe8, 0x93, 0x4a, 0x3b, 0x7b, 0x02, - 0x4a, 0xbb, 0xe8, 0x39, 0x24, 0xa1, 0xee, 0xcc, 0x1b, 0x6a, 0x0d, 0x78, 0x9b, 0x3b, 0x11, 0x6f, - 0xa8, 0x95, 0xf0, 0xf6, 0x2e, 0x28, 0x4c, 0x7e, 0x5c, 0xae, 0x26, 0x06, 0x7f, 0x78, 0x0d, 0x4c, - 0x50, 0xcd, 0xc5, 0x96, 0x32, 0xcf, 0x65, 0xe3, 0x9c, 0x4b, 0xbd, 0x1e, 0xb1, 0xb9, 0x1e, 0x19, - 0xaf, 0x65, 0xbe, 0x79, 0x9c, 0x9f, 0xf8, 0xe7, 0x71, 0x7e, 0x42, 0xbb, 0x08, 0x17, 0x52, 0x72, - 0x56, 0xe4, 0xf4, 0xd7, 0x12, 0x97, 0xac, 0x5d, 0x17, 0x39, 0xde, 0x6d, 0x62, 0x61, 0x17, 0xdb, - 0x28, 0xc4, 0x16, 0x97, 0xb5, 0x51, 0x2f, 0x6f, 0x01, 0xb2, 0xa2, 0xbc, 0xba, 0x7a, 0x03, 0x9d, - 0x0a, 0xab, 0x58, 0xf2, 0x32, 0x9c, 0xc6, 0x0d, 0xdf, 0xac, 0xf3, 0xe2, 0x9b, 0xd2, 0xa3, 0x81, - 0xbc, 0x02, 0xd3, 0x14, 0x13, 0x4b, 0xd4, 0x5d, 0x3c, 0xd2, 0xd6, 0xe0, 0xd2, 0x50, 0x1a, 0x82, - 0x6c, 0x18, 0x97, 0x66, 0x2d, 0x12, 0x98, 0x4f, 0x3b, 0xfd, 0xc7, 0x28, 0xa2, 0x7d, 0x3a, 0x70, - 0x2a, 0xa1, 0x03, 0x6b, 0x30, 0x4b, 0x9a, 0x9e, 0x11, 0x74, 0x76, 0x8c, 0xb9, 0x66, 0x49, 0xd3, - 0x13, 0x5e, 0xb4, 0x02, 0xe4, 0xd2, 0xbd, 0xf6, 0x06, 0x71, 0xa1, 0x4a, 0xed, 0x1d, 0xcb, 0x7a, - 0x7d, 0x4a, 0xd7, 0x00, 0x44, 0x5f, 0x45, 0x95, 0xc9, 0xc2, 0xe4, 0xfa, 0xcc, 0x96, 0x5a, 0x4c, - 0xb4, 0x6b, 0x45, 0xe1, 0x47, 0xef, 0x41, 0x6b, 0x2a, 0x28, 0x49, 0x1a, 0x82, 0xe3, 0xcf, 0x12, - 0x37, 0xb2, 0xfa, 0xb3, 0xbb, 0x67, 0xb8, 0x83, 0x1d, 0xbb, 0x1e, 0x1e, 0x97, 0xeb, 0x36, 0x64, - 0x0e, 0x90, 0x6b, 0x20, 0xcb, 0x0a, 0xe2, 0x77, 0x45, 0x79, 0xfe, 0x64, 0x63, 0x39, 0xce, 0xe9, - 0x1d, 0xcb, 0x0a, 0x30, 0xa5, 0xfb, 0x61, 0xe0, 0x10, 0x5b, 0x3f, 0x73, 0x80, 0x5c, 0x36, 0xc3, - 0x32, 0xe0, 0x21, 0xf7, 0xca, 0x33, 0x60, 0x4a, 0x8f, 0x47, 0x9a, 0x06, 0x85, 0x61, 0xfc, 0xc4, - 0x21, 0xbe, 0x92, 0x40, 0xae, 0x52, 0x7b, 0x0f, 0xb3, 0xd7, 0x51, 0x80, 0xde, 0x24, 0x7d, 0xed, - 0x3f, 0xa0, 0x0e, 0x32, 0x10, 0x04, 0x7f, 0x94, 0xe2, 0x72, 0xa3, 0xa1, 0x1f, 0xe0, 0x0a, 0x09, - 0x71, 0xc0, 0x9f, 0xe0, 0x9d, 0xa8, 0x93, 0x3e, 0xde, 0xe3, 0x5d, 0x86, 0x6c, 0xdc, 0x89, 0x1b, - 0x4c, 0x3b, 0x38, 0xd7, 0xb9, 0xad, 0xfc, 0x40, 0x52, 0x54, 0x76, 0x77, 0x62, 0x3f, 0xb7, 0x1e, - 0x35, 0xb0, 0x3e, 0x83, 0xba, 0x03, 0xed, 0x7f, 0xb0, 0x36, 0x82, 0x97, 0xe0, 0xff, 0x80, 0x5f, - 0x42, 0xd4, 0x43, 0x8a, 0xd3, 0xed, 0xd7, 0x51, 0x80, 0xe9, 0xf5, 0x96, 0x59, 0xe7, 0xa2, 0x74, - 0xac, 0x33, 0x28, 0xc0, 0x22, 0xe8, 0x37, 0x70, 0x1c, 0x6a, 0xbd, 0x33, 0xd4, 0x2e, 0xc3, 0xfa, - 0x38, 0x97, 0x82, 0x9e, 0xcd, 0x05, 0x60, 0x17, 0xb9, 0x4e, 0x8d, 0xc9, 0xee, 0x5e, 0xa4, 0x13, - 0x8e, 0x4f, 0x4e, 0x9a, 0x54, 0x54, 0xf3, 0x29, 0x8e, 0x3a, 0x54, 0xb6, 0x7e, 0xca, 0xc2, 0x64, - 0x95, 0xda, 0xf2, 0x1d, 0x98, 0xe9, 0x6d, 0x49, 0x07, 0x6f, 0xa5, 0xbf, 0xa3, 0x55, 0xdf, 0x1a, - 0x03, 0x10, 0xed, 0xe2, 0xe7, 0x30, 0x97, 0x68, 0x77, 0xb5, 0xd4, 0xa5, 0x7d, 0x18, 0xf5, 0xf2, - 0x78, 0x8c, 0xf0, 0x70, 0x07, 0x66, 0x7a, 0x7b, 0xb2, 0x54, 0xea, 0x3d, 0x80, 0x74, 0xea, 0x29, - 0x8d, 0x92, 0x7c, 0x0f, 0x16, 0x06, 0x9a, 0xa4, 0xff, 0xa6, 0x2f, 0xee, 0x47, 0xa9, 0x57, 0x8e, - 0x82, 0x12, 0x7e, 0x5a, 0xb0, 0x32, 0xe4, 0xe1, 0x4a, 0x0d, 0x43, 0x3a, 0x56, 0xdd, 0x3a, 0x3a, - 0x56, 0x78, 0xf6, 0x61, 0x29, 0xed, 0x19, 0x1a, 0x12, 0xa1, 0x01, 0xa0, 0x5a, 0x3a, 0x22, 0x50, - 0x38, 0xfc, 0x0c, 0x66, 0xfb, 0x9f, 0x97, 0x4b, 0x69, 0x3b, 0xf4, 0x41, 0xd4, 0xb7, 0xc7, 0x42, - 0xc4, 0xf6, 0x4d, 0x38, 0x97, 0xfe, 0x32, 0xa4, 0xee, 0x91, 0x0a, 0x55, 0x37, 0x8f, 0x0c, 0x15, - 0x6e, 0x4d, 0x98, 0x4f, 0x6a, 0xf9, 0x5a, 0xda, 0x2e, 0x09, 0x90, 0xfa, 0xce, 0x11, 0x40, 0xc2, - 0xc9, 0x97, 0xa0, 0x0c, 0xd5, 0xe3, 0x21, 0xf9, 0x96, 0x8e, 0x56, 0xaf, 0xbe, 0x0a, 0x5a, 0xf8, - 0xff, 0x56, 0x82, 0x8b, 0xa3, 0x15, 0x35, 0x35, 0x72, 0x23, 0x97, 0xa8, 0xef, 0xbd, 0xf2, 0x92, - 0xde, 0xdc, 0x4d, 0x53, 0xd0, 0xd4, 0xdc, 0x4d, 0x01, 0xa6, 0xe7, 0xee, 0x08, 0xa9, 0x94, 0xef, - 0x42, 0xb6, 0xef, 0x17, 0x6c, 0x21, 0xbd, 0xe0, 0xba, 0x08, 0x75, 0x7d, 0x1c, 0x42, 0xec, 0xfd, - 0x83, 0x04, 0xf9, 0x71, 0xdf, 0x8f, 0xb6, 0x87, 0xc7, 0x6a, 0xe8, 0x22, 0xf5, 0xfd, 0x63, 0x2c, - 0xea, 0xb0, 0x2a, 0xdf, 0x78, 0xfa, 0x22, 0x27, 0x3d, 0x7b, 0x91, 0x93, 0xfe, 0x7e, 0x91, 0x93, - 0xbe, 0x7b, 0x99, 0x9b, 0x78, 0xf6, 0x32, 0x37, 0xf1, 0xe7, 0xcb, 0xdc, 0xc4, 0xdd, 0xad, 0x9e, - 0x9f, 0x06, 0xfb, 0xdc, 0xc1, 0xc6, 0x0d, 0x54, 0xa3, 0xa5, 0xf8, 0xdb, 0xda, 0xc1, 0xe6, 0xd5, - 0x52, 0xab, 0xe7, 0x7b, 0x1d, 0xfb, 0xa9, 0x50, 0x9b, 0xe6, 0x5f, 0xcb, 0xb6, 0xff, 0x0d, 0x00, - 0x00, 0xff, 0xff, 0x10, 0x8e, 0x60, 0x6c, 0xcf, 0x13, 0x00, 0x00, + // 1480 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcf, 0x6f, 0xdc, 0xc4, + 0x17, 0x8f, 0x9b, 0x34, 0x4d, 0x5f, 0x36, 0xbf, 0x9c, 0x34, 0x75, 0x9c, 0x6f, 0x77, 0x53, 0xe7, + 0x0b, 0x84, 0xd2, 0x24, 0x4a, 0x52, 0x09, 0x51, 0xe0, 0x90, 0x4d, 0x8a, 0x58, 0xa9, 0xa9, 0x90, + 0xd3, 0x52, 0xa9, 0x12, 0x32, 0xb3, 0xf6, 0xd4, 0x6b, 0xd5, 0x1e, 0x6f, 0x3d, 0xde, 0x74, 0xcb, + 0x01, 0x71, 0x41, 0xe2, 0x82, 0x04, 0x42, 0xe2, 0x88, 0x7a, 0xe0, 0x80, 0xc4, 0x0d, 0xf5, 0x8f, + 0xa8, 0xc4, 0xa5, 0xea, 0x09, 0x71, 0x88, 0x50, 0x7b, 0xe1, 0x9c, 0x33, 0x07, 0x34, 0x63, 0xef, + 0xac, 0xed, 0xcc, 0x26, 0x69, 0x1a, 0x7a, 0xca, 0xce, 0xbc, 0xcf, 0xcc, 0xfb, 0xcc, 0x9b, 0x37, + 0x9f, 0xf7, 0x62, 0xd0, 0x68, 0x1c, 0x79, 0x0e, 0x5e, 0xa6, 0x31, 0xba, 0x87, 0xbd, 0xba, 0xbd, + 0x1c, 0xb7, 0x97, 0x9a, 0x51, 0x18, 0x87, 0xea, 0x58, 0x62, 0x59, 0xea, 0x58, 0xf4, 0x8b, 0x45, + 0xa8, 0x67, 0x23, 0x0b, 0xd9, 0x76, 0xd8, 0x22, 0x71, 0xb2, 0x46, 0xaf, 0x14, 0x21, 0x3b, 0xc8, + 0xf7, 0x1c, 0x14, 0x87, 0x51, 0x0a, 0x98, 0x72, 0x43, 0x37, 0xe4, 0x3f, 0x97, 0xd9, 0xaf, 0x74, + 0x76, 0xc6, 0x0e, 0x69, 0x10, 0x52, 0x2b, 0x31, 0x24, 0x83, 0xc4, 0x64, 0xfc, 0x7e, 0x0a, 0x8c, + 0x2d, 0xea, 0xde, 0x6a, 0x3a, 0x28, 0xc6, 0x35, 0x42, 0x70, 0x64, 0x62, 0x07, 0x07, 0xcd, 0xd8, + 0x0b, 0x89, 0x89, 0x62, 0x5c, 0x0d, 0x5b, 0xc4, 0xa1, 0xaa, 0x06, 0x67, 0xec, 0x08, 0x33, 0x47, + 0x9a, 0x32, 0xa7, 0x2c, 0x9c, 0x35, 0x3b, 0x43, 0x75, 0x06, 0x86, 0xec, 0x06, 0xf2, 0x88, 0xe5, + 0x39, 0xda, 0xa9, 0xd4, 0xc4, 0xc6, 0x35, 0x47, 0x7d, 0x00, 0x33, 0x01, 0x33, 0xb0, 0x5d, 0xad, + 0x48, 0x6c, 0x6b, 0x45, 0x28, 0xc6, 0x5a, 0x3f, 0xc3, 0x56, 0x3f, 0x78, 0xb2, 0x5b, 0xe9, 0xfb, + 0x73, 0xb7, 0xf2, 0xa6, 0xeb, 0xc5, 0x8d, 0x56, 0x7d, 0xc9, 0x0e, 0x83, 0x94, 0x5f, 0xfa, 0x67, + 0x91, 0x3a, 0xf7, 0x96, 0xe3, 0x87, 0x4d, 0x4c, 0x97, 0x36, 0xb1, 0xfd, 0xec, 0xf1, 0x22, 0xa4, + 0xf4, 0x37, 0xb1, 0x6d, 0x4e, 0x07, 0x1e, 0x91, 0x70, 0xe6, 0x8e, 0x51, 0xbb, 0x87, 0xe3, 0x81, + 0x13, 0x71, 0x8c, 0xda, 0x12, 0xc7, 0xc6, 0x65, 0xb8, 0x74, 0x78, 0x30, 0x4d, 0x4c, 0x9b, 0x21, + 0xa1, 0xd8, 0xf8, 0x5e, 0x81, 0xd1, 0x2d, 0xea, 0x5e, 0xf7, 0xee, 0xb7, 0x3c, 0x67, 0x9b, 0x5d, + 0xe9, 0x01, 0x71, 0xfe, 0x08, 0x06, 0x51, 0xc0, 0x52, 0x21, 0x89, 0x72, 0x75, 0xe9, 0x25, 0x0e, + 0x50, 0x23, 0xb1, 0x99, 0xae, 0x56, 0x2f, 0x00, 0x34, 0x42, 0x1a, 0x5b, 0x0e, 0x26, 0x61, 0x90, + 0xdc, 0x82, 0x79, 0x96, 0xcd, 0x6c, 0xb2, 0x09, 0x43, 0x83, 0xe9, 0x3c, 0x25, 0xc1, 0xf6, 0x67, + 0x05, 0x26, 0x98, 0x69, 0x7b, 0xeb, 0xf5, 0x12, 0x5e, 0x84, 0x49, 0x9f, 0x06, 0x56, 0x1c, 0xde, + 0xc3, 0xc4, 0xf2, 0xea, 0x76, 0x8e, 0xf9, 0xb8, 0x4f, 0x83, 0x9b, 0xcc, 0x52, 0xab, 0xdb, 0xc9, + 0x01, 0x6e, 0xc0, 0xcc, 0x3e, 0x96, 0x9d, 0x33, 0xa8, 0x2b, 0x30, 0x15, 0x47, 0x88, 0x50, 0x64, + 0xf3, 0x7c, 0xb0, 0xc3, 0xa0, 0xe9, 0xe3, 0x18, 0x73, 0xea, 0x43, 0xe6, 0x64, 0xc6, 0xb6, 0x91, + 0x9a, 0x8c, 0x5f, 0x14, 0x18, 0xdb, 0xa2, 0xee, 0x86, 0x8f, 0x51, 0x54, 0x45, 0x3e, 0x22, 0x36, + 0x3e, 0xde, 0x6b, 0xe8, 0xc6, 0xa3, 0xff, 0x95, 0xe2, 0xc1, 0x9c, 0x37, 0x10, 0x21, 0xd8, 0x4f, + 0x52, 0xd9, 0xec, 0x0c, 0x8d, 0x19, 0x38, 0x5f, 0x60, 0x2a, 0x2e, 0xef, 0xd7, 0x24, 0xd5, 0x58, + 0x3a, 0xe2, 0xe0, 0x75, 0xdd, 0xdc, 0x2c, 0xf0, 0xc4, 0xb2, 0xbe, 0x08, 0x49, 0xfa, 0xde, 0xcd, + 0x21, 0x36, 0x71, 0x27, 0x24, 0x58, 0xd5, 0x61, 0x28, 0xc2, 0x36, 0xf6, 0x76, 0x70, 0x94, 0x9e, + 0x43, 0x8c, 0xd3, 0x24, 0xcc, 0x90, 0x15, 0xe7, 0xf8, 0xed, 0x34, 0x4c, 0x72, 0x93, 0xeb, 0xd1, + 0x18, 0x47, 0x1f, 0x77, 0x76, 0xfb, 0x10, 0x46, 0xec, 0x90, 0x10, 0x9c, 0xdc, 0x6b, 0x27, 0xf8, + 0x55, 0x6d, 0x6f, 0xb7, 0x32, 0xf5, 0x10, 0x05, 0xfe, 0x55, 0x23, 0x67, 0x36, 0xcc, 0x52, 0x77, + 0x5c, 0x73, 0x54, 0x03, 0x4a, 0x75, 0x6c, 0x37, 0xd6, 0x56, 0x9b, 0x11, 0xbe, 0xeb, 0xb5, 0xb5, + 0x12, 0x27, 0x94, 0x9b, 0x53, 0xaf, 0xe4, 0x1e, 0x4e, 0xa2, 0x22, 0xe7, 0xf6, 0x76, 0x2b, 0x13, + 0xc9, 0xfe, 0x5d, 0x9b, 0x91, 0x79, 0x4f, 0xea, 0x0a, 0x9c, 0xed, 0xe6, 0xec, 0x69, 0xbe, 0x68, + 0x6a, 0x6f, 0xb7, 0x32, 0x9e, 0x2c, 0x12, 0x26, 0xc3, 0x1c, 0xf2, 0xd2, 0x0c, 0xce, 0x5e, 0xcc, + 0x60, 0xfe, 0x62, 0x6e, 0x40, 0x92, 0xa2, 0x77, 0x71, 0x64, 0xa5, 0x97, 0xce, 0xce, 0x0a, 0x7c, + 0xdb, 0xf2, 0xde, 0x6e, 0x45, 0x4f, 0xb6, 0x95, 0x80, 0x0c, 0x73, 0xa2, 0x33, 0xbb, 0x91, 0x4c, + 0xf2, 0x94, 0x1c, 0x6f, 0x91, 0x7a, 0x48, 0x1c, 0x8f, 0xb8, 0x56, 0x13, 0x47, 0x5e, 0xe8, 0x68, + 0xc3, 0x73, 0xca, 0xc2, 0x40, 0x75, 0x76, 0x6f, 0xb7, 0x72, 0x3e, 0xd9, 0xac, 0x88, 0x30, 0xcc, + 0x31, 0x31, 0xf5, 0x09, 0x9f, 0x51, 0x7d, 0x98, 0x64, 0x42, 0x5f, 0x54, 0xda, 0x91, 0x13, 0x50, + 0xda, 0x89, 0xc0, 0x23, 0x05, 0x75, 0x67, 0xde, 0x50, 0x7b, 0x9f, 0xb7, 0xd1, 0x13, 0xf1, 0x86, + 0xda, 0x05, 0x6f, 0xef, 0x82, 0xc6, 0xe4, 0xc7, 0xe7, 0x6a, 0x62, 0xf1, 0xc2, 0x6b, 0x61, 0x82, + 0xea, 0x3e, 0x76, 0xb4, 0x31, 0x2e, 0x1b, 0xe7, 0x7c, 0x1a, 0x64, 0xc4, 0xe6, 0x5a, 0x62, 0xbc, + 0x3a, 0xf4, 0xcd, 0xa3, 0x4a, 0xdf, 0xdf, 0x8f, 0x2a, 0x7d, 0xc6, 0x05, 0x98, 0x95, 0xe4, 0xac, + 0xc8, 0xe9, 0xaf, 0x15, 0x2e, 0x59, 0x1b, 0x3e, 0xf2, 0x82, 0x5b, 0xc4, 0xc1, 0x3e, 0x76, 0x51, + 0x8c, 0x1d, 0x2e, 0x6b, 0x07, 0x55, 0xde, 0x39, 0x28, 0x89, 0xe7, 0xd5, 0xd5, 0x1b, 0xe8, 0xbc, + 0xb0, 0x9a, 0xa3, 0x4e, 0xc1, 0x69, 0xdc, 0x0c, 0xed, 0x06, 0x7f, 0x7c, 0x03, 0x66, 0x32, 0x50, + 0xa7, 0x61, 0x90, 0x62, 0xe2, 0x88, 0x77, 0x97, 0x8e, 0x8c, 0x79, 0xb8, 0xd8, 0x93, 0x86, 0x20, + 0x1b, 0xa7, 0x4f, 0xb3, 0x9e, 0x08, 0xcc, 0xa7, 0x9d, 0xfe, 0xe3, 0x20, 0xa2, 0x39, 0x1d, 0x38, + 0x55, 0xd0, 0x81, 0x79, 0x18, 0x21, 0xad, 0xc0, 0x8a, 0x3a, 0x3b, 0xa6, 0x5c, 0x4b, 0xa4, 0x15, + 0x08, 0x2f, 0xc6, 0x1c, 0x94, 0xe5, 0x5e, 0xb3, 0x41, 0x1c, 0xdf, 0xa2, 0xee, 0xba, 0xe3, 0xbc, + 0x3a, 0xa5, 0xab, 0x00, 0xa2, 0xaf, 0xa2, 0x5a, 0xff, 0x5c, 0xff, 0xc2, 0xf0, 0xaa, 0xbe, 0x54, + 0x68, 0xd7, 0x96, 0x84, 0x1f, 0x33, 0x83, 0x36, 0x74, 0xd0, 0x8a, 0x34, 0x04, 0xc7, 0x9f, 0x14, + 0x6e, 0x64, 0xef, 0xcf, 0xed, 0x9e, 0xe1, 0x36, 0xf6, 0xdc, 0x46, 0x7c, 0x5c, 0xae, 0x6b, 0x30, + 0xb4, 0x83, 0x7c, 0x0b, 0x39, 0x4e, 0x94, 0xd6, 0x15, 0xed, 0xd9, 0xe3, 0xc5, 0xa9, 0x34, 0xa7, + 0xd7, 0x1d, 0x27, 0xc2, 0x94, 0x6e, 0xc7, 0x91, 0x47, 0x5c, 0xf3, 0xcc, 0x0e, 0xf2, 0xd9, 0x0c, + 0xcb, 0x80, 0x07, 0xdc, 0x2b, 0xcf, 0x80, 0x01, 0x33, 0x1d, 0x19, 0x06, 0xcc, 0xf5, 0xe2, 0x27, + 0x0e, 0xf1, 0x95, 0x02, 0xea, 0x16, 0x75, 0x37, 0x31, 0xab, 0x8e, 0x02, 0xf4, 0x3a, 0xe9, 0x1b, + 0xff, 0x03, 0x7d, 0x3f, 0x03, 0x41, 0xf0, 0x47, 0x25, 0x7d, 0x6e, 0x34, 0x0e, 0x23, 0x5c, 0x23, + 0x31, 0x8e, 0x78, 0x09, 0x5e, 0x4f, 0x3a, 0xe9, 0xe3, 0x15, 0xef, 0x2a, 0x94, 0xd2, 0x4e, 0xdc, + 0x62, 0xda, 0xc1, 0xb9, 0x8e, 0xae, 0x56, 0xf6, 0x25, 0x45, 0x6d, 0x63, 0x3d, 0xf5, 0x73, 0xf3, + 0x61, 0x13, 0x9b, 0xc3, 0xa8, 0x3b, 0x30, 0xde, 0x80, 0xf9, 0x03, 0x78, 0x09, 0xfe, 0xf7, 0xf9, + 0x25, 0x24, 0x3d, 0xa4, 0x38, 0xdd, 0x76, 0x03, 0x45, 0x98, 0x5e, 0x6b, 0xdb, 0x0d, 0x2e, 0x4a, + 0xc7, 0x3a, 0x83, 0x06, 0x2c, 0x82, 0x61, 0x13, 0xa7, 0xa1, 0x36, 0x3b, 0x43, 0xe3, 0x12, 0x2c, + 0x1c, 0xe6, 0x52, 0xd0, 0x6b, 0xf1, 0x2e, 0xb0, 0x2b, 0x10, 0x4c, 0xce, 0xfe, 0xfb, 0x5e, 0xc2, + 0x98, 0xe5, 0x1a, 0x99, 0x77, 0x2b, 0x38, 0xb9, 0x5c, 0x94, 0x36, 0x90, 0xef, 0xd5, 0x59, 0x29, + 0xd8, 0x4c, 0x30, 0x5e, 0x48, 0x4e, 0x3a, 0x50, 0x89, 0x0e, 0x49, 0x1c, 0x75, 0xa8, 0xac, 0xfe, + 0x53, 0x82, 0xfe, 0x2d, 0xea, 0xaa, 0xb7, 0x61, 0x38, 0xdb, 0x26, 0xef, 0xcf, 0x94, 0x7c, 0x97, + 0xad, 0xbf, 0x75, 0x08, 0x40, 0xb4, 0xb0, 0x9f, 0xc3, 0x68, 0xa1, 0x05, 0x37, 0xa4, 0x4b, 0x73, + 0x18, 0xfd, 0xd2, 0xe1, 0x18, 0xe1, 0xe1, 0x36, 0x0c, 0x67, 0xfb, 0x44, 0x29, 0xf5, 0x0c, 0x40, + 0x4e, 0x5d, 0xd2, 0xbc, 0xa9, 0x77, 0x61, 0x7c, 0x5f, 0xe3, 0xf6, 0x7f, 0xf9, 0xe2, 0x3c, 0x4a, + 0xbf, 0x7c, 0x14, 0x94, 0xf0, 0xd3, 0x86, 0xe9, 0x1e, 0xc5, 0x54, 0x1a, 0x06, 0x39, 0x56, 0x5f, + 0x3d, 0x3a, 0x56, 0x78, 0x0e, 0x61, 0x52, 0x56, 0x1a, 0x7b, 0x44, 0x68, 0x1f, 0x50, 0x5f, 0x3e, + 0x22, 0x50, 0x38, 0xfc, 0x0c, 0x46, 0xf2, 0x25, 0xef, 0xa2, 0x6c, 0x87, 0x1c, 0x44, 0x7f, 0xfb, + 0x50, 0x88, 0xd8, 0xbe, 0x05, 0xe7, 0xe4, 0xd5, 0x4a, 0xba, 0x87, 0x14, 0xaa, 0xaf, 0x1c, 0x19, + 0x2a, 0xdc, 0xda, 0x30, 0x56, 0xac, 0x2f, 0xf3, 0xb2, 0x5d, 0x0a, 0x20, 0xfd, 0x9d, 0x23, 0x80, + 0x84, 0x93, 0x2f, 0x41, 0xeb, 0x59, 0x23, 0x7a, 0xe4, 0x9b, 0x1c, 0xad, 0x5f, 0x79, 0x19, 0xb4, + 0xf0, 0xff, 0xad, 0x02, 0x17, 0x0e, 0x56, 0x79, 0x69, 0xe4, 0x0e, 0x5c, 0xa2, 0xbf, 0xf7, 0xd2, + 0x4b, 0xb2, 0xb9, 0x2b, 0x53, 0x50, 0x69, 0xee, 0x4a, 0x80, 0xf2, 0xdc, 0x3d, 0x40, 0x2a, 0xd5, + 0x3b, 0x50, 0xca, 0xfd, 0x57, 0x3d, 0x27, 0x7f, 0x70, 0x5d, 0x84, 0xbe, 0x70, 0x18, 0x22, 0xab, + 0x92, 0x85, 0x12, 0x25, 0x55, 0xc9, 0x3c, 0x46, 0xae, 0x92, 0xf2, 0x9a, 0xa3, 0xfe, 0xa0, 0x40, + 0xe5, 0xb0, 0xaf, 0x66, 0x6b, 0xbd, 0x6f, 0xa3, 0xe7, 0x22, 0xfd, 0xfd, 0x63, 0x2c, 0xea, 0xb0, + 0xaa, 0x5e, 0x7f, 0xf2, 0xbc, 0xac, 0x3c, 0x7d, 0x5e, 0x56, 0xfe, 0x7a, 0x5e, 0x56, 0xbe, 0x7b, + 0x51, 0xee, 0x7b, 0xfa, 0xa2, 0xdc, 0xf7, 0xc7, 0x8b, 0x72, 0xdf, 0x9d, 0xd5, 0x4c, 0xc1, 0xdd, + 0xe6, 0x0e, 0x16, 0xaf, 0xa3, 0x3a, 0x5d, 0x4e, 0xbf, 0x28, 0xee, 0xac, 0x5c, 0x59, 0x6e, 0x67, + 0xbe, 0x52, 0xb2, 0x02, 0x5c, 0x1f, 0xe4, 0xdf, 0x08, 0xd7, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, + 0x53, 0xce, 0xb3, 0x94, 0xc5, 0x14, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1527,6 +1612,7 @@ type MsgClient interface { UpdateValidatorSharesExchRate(ctx context.Context, in *MsgUpdateValidatorSharesExchRate, opts ...grpc.CallOption) (*MsgUpdateValidatorSharesExchRateResponse, error) CalibrateDelegation(ctx context.Context, in *MsgCalibrateDelegation, opts ...grpc.CallOption) (*MsgCalibrateDelegationResponse, error) ClearBalance(ctx context.Context, in *MsgClearBalance, opts ...grpc.CallOption) (*MsgClearBalanceResponse, error) + UndelegateHost(ctx context.Context, in *MsgUndelegateHost, opts ...grpc.CallOption) (*MsgUndelegateHostResponse, error) UpdateInnerRedemptionRateBounds(ctx context.Context, in *MsgUpdateInnerRedemptionRateBounds, opts ...grpc.CallOption) (*MsgUpdateInnerRedemptionRateBoundsResponse, error) } @@ -1655,6 +1741,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) (*MsgUndelegateHostResponse, error) { + out := new(MsgUndelegateHostResponse) + err := c.cc.Invoke(ctx, "/stride.stakeibc.Msg/UndelegateHost", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *msgClient) UpdateInnerRedemptionRateBounds(ctx context.Context, in *MsgUpdateInnerRedemptionRateBounds, opts ...grpc.CallOption) (*MsgUpdateInnerRedemptionRateBoundsResponse, error) { out := new(MsgUpdateInnerRedemptionRateBoundsResponse) err := c.cc.Invoke(ctx, "/stride.stakeibc.Msg/UpdateInnerRedemptionRateBounds", in, out, opts...) @@ -1679,6 +1774,7 @@ type MsgServer interface { UpdateValidatorSharesExchRate(context.Context, *MsgUpdateValidatorSharesExchRate) (*MsgUpdateValidatorSharesExchRateResponse, error) CalibrateDelegation(context.Context, *MsgCalibrateDelegation) (*MsgCalibrateDelegationResponse, error) ClearBalance(context.Context, *MsgClearBalance) (*MsgClearBalanceResponse, error) + UndelegateHost(context.Context, *MsgUndelegateHost) (*MsgUndelegateHostResponse, error) UpdateInnerRedemptionRateBounds(context.Context, *MsgUpdateInnerRedemptionRateBounds) (*MsgUpdateInnerRedemptionRateBoundsResponse, error) } @@ -1725,6 +1821,9 @@ func (*UnimplementedMsgServer) CalibrateDelegation(ctx context.Context, req *Msg 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) (*MsgUndelegateHostResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UndelegateHost not implemented") +} func (*UnimplementedMsgServer) UpdateInnerRedemptionRateBounds(ctx context.Context, req *MsgUpdateInnerRedemptionRateBounds) (*MsgUpdateInnerRedemptionRateBoundsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateInnerRedemptionRateBounds not implemented") } @@ -1967,6 +2066,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) +} + func _Msg_UpdateInnerRedemptionRateBounds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(MsgUpdateInnerRedemptionRateBounds) if err := dec(in); err != nil { @@ -2041,6 +2158,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "ClearBalance", Handler: _Msg_ClearBalance_Handler, }, + { + MethodName: "UndelegateHost", + Handler: _Msg_UndelegateHost_Handler, + }, { MethodName: "UpdateInnerRedemptionRateBounds", Handler: _Msg_UpdateInnerRedemptionRateBounds_Handler, @@ -3039,6 +3160,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 (m *MsgCalibrateDelegation) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -3538,6 +3722,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 (m *MsgCalibrateDelegation) Size() (n int) { if m == nil { return 0 @@ -6467,6 +6675,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 (m *MsgCalibrateDelegation) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0