Skip to content

Commit

Permalink
add resume host zone func
Browse files Browse the repository at this point in the history
  • Loading branch information
shellvish committed Oct 14, 2023
1 parent 624d924 commit 2a0f911
Show file tree
Hide file tree
Showing 11 changed files with 711 additions and 98 deletions.
7 changes: 7 additions & 0 deletions proto/stride/stakeibc/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ service Msg {
rpc UndelegateHost(MsgUndelegateHost) returns (MsgUndelegateHostResponse);
rpc UpdateInnerRedemptionRateBounds(MsgUpdateInnerRedemptionRateBounds)
returns (MsgUpdateInnerRedemptionRateBoundsResponse);
rpc ResumeHostZone(MsgResumeHostZone) returns (MsgResumeHostZoneResponse);
}

message MsgUpdateInnerRedemptionRateBounds {
Expand Down Expand Up @@ -188,3 +189,9 @@ message MsgCalibrateDelegation {
string valoper = 3;
}
message MsgCalibrateDelegationResponse {}

message MsgResumeHostZone {
string creator = 1;
string chain_id = 2;
}
message MsgResumeHostZoneResponse {}
1 change: 1 addition & 0 deletions x/stakeibc/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func GetTxCmd() *cobra.Command {
cmd.AddCommand(CmdClearBalance())
cmd.AddCommand(CmdUndelegateHost())
cmd.AddCommand(CmdUpdateInnerRedemptionRateBounds())
cmd.AddCommand(CmdResumeHostZone())

return cmd
}
39 changes: 39 additions & 0 deletions x/stakeibc/client/cli/tx_resume_host_zone.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package cli

import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/spf13/cobra"

"github.com/Stride-Labs/stride/v15/x/stakeibc/types"
)

func CmdResumeHostZone() *cobra.Command {
cmd := &cobra.Command{
Use: "resume-host-zone [chainid]",
Short: "Broadcast message resume-host-zone",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) (err error) {
argChainId := args[0]

clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

msg := types.NewMsgResumeHostZone(
clientCtx.GetFromAddress().String(),
argChainId,
)
if err := msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
3 changes: 3 additions & 0 deletions x/stakeibc/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ func NewMessageHandler(k keeper.Keeper) sdk.Handler {
case *types.MsgUpdateInnerRedemptionRateBounds:
res, err := msgServer.UpdateInnerRedemptionRateBounds(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *types.MsgResumeHostZone:
res, err := msgServer.ResumeHostZone(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
default:
errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg)
return nil, errorsmod.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
Expand Down
36 changes: 36 additions & 0 deletions x/stakeibc/keeper/msg_server_resume_host_zone.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package keeper

import (
"context"
"fmt"

"github.com/Stride-Labs/stride/v15/x/stakeibc/types"

errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
)

func (k msgServer) ResumeHostZone(goCtx context.Context, msg *types.MsgResumeHostZone) (*types.MsgResumeHostZoneResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

// Get Host Zone
hostZone, found := k.GetHostZone(ctx, msg.ChainId)
if !found {
errMsg := fmt.Sprintf("invalid chain id, zone for %s not found", msg.ChainId)
k.Logger(ctx).Error(errMsg)
return nil, errorsmod.Wrapf(types.ErrHostZoneNotFound, errMsg)
}

// Check the zone is halted
if !hostZone.Halted {
errMsg := fmt.Sprintf("invalid chain id, zone for %s not halted", msg.ChainId)
k.Logger(ctx).Error(errMsg)
return nil, errorsmod.Wrapf(types.ErrHostZoneNotHalted, errMsg)
}

// Resume zone
hostZone.Halted = false
k.SetHostZone(ctx, hostZone)

return &types.MsgResumeHostZoneResponse{}, nil
}
99 changes: 99 additions & 0 deletions x/stakeibc/keeper/msg_server_resume_host_zone_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package keeper_test

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
_ "github.com/stretchr/testify/suite"

stakeibctypes "github.com/Stride-Labs/stride/v15/x/stakeibc/types"
)

type ResumeHostZoneTestCase struct {
validMsg stakeibctypes.MsgResumeHostZone
zone stakeibctypes.HostZone
}

func (s *KeeperTestSuite) SetupResumeHostZone() ResumeHostZoneTestCase {
// Register a host zone
hostZone := stakeibctypes.HostZone{
ChainId: HostChainId,
HostDenom: Atom,
IbcDenom: IbcAtom,
RedemptionRate: sdk.NewDec(1.0),
MinRedemptionRate: sdk.NewDec(9).Quo(sdk.NewDec(10)),
MaxRedemptionRate: sdk.NewDec(15).Quo(sdk.NewDec(10)),
Halted: true,
}

s.App.StakeibcKeeper.SetHostZone(s.Ctx, hostZone)

defaultMsg := stakeibctypes.MsgResumeHostZone{
Creator: s.TestAccs[0].String(),
ChainId: HostChainId,
}

return ResumeHostZoneTestCase{
validMsg: defaultMsg,
zone: hostZone,
}
}

// Verify that bounds can be set successfully
func (s *KeeperTestSuite) TestResumeHostZone_Success() {
tc := s.SetupResumeHostZone()

// Set the inner bounds on the host zone
_, err := s.GetMsgServer().ResumeHostZone(s.Ctx, &tc.validMsg)
s.Require().NoError(err, "should not throw an error")

// Confirm the inner bounds were set
zone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, HostChainId)
s.Require().True(found, "host zone should be in the store")

s.Require().False(zone.Halted, "host zone should not be halted")
}

// verify that non-admins can't call the tx
func (s *KeeperTestSuite) TestResumeHostZone_NonAdmin() {
tc := s.SetupResumeHostZone()

invalidMsg := tc.validMsg
invalidMsg.Creator = s.TestAccs[1].String()

err := invalidMsg.ValidateBasic()
s.Require().Error(err, "nonadmins shouldn't be able to call this tx")
}

// verify that the function can't be called on missing zones
func (s *KeeperTestSuite) TestResumeHostZone_MissingZones() {
tc := s.SetupResumeHostZone()

invalidMsg := tc.validMsg
invalidChainId := "invalid-chain"
invalidMsg.ChainId = invalidChainId

// Set the inner bounds on the host zone
_, err := s.GetMsgServer().ResumeHostZone(s.Ctx, &invalidMsg)

s.Require().Error(err, "shouldn't be able to call tx on missing zones")
expectedErrorMsg := fmt.Sprintf("invalid chain id, zone for %s not found: host zone not found", invalidChainId)
s.Require().Equal(expectedErrorMsg, err.Error(), "should return correct error msg")
}

// verify that the function can't be called on unhalted zones
func (s *KeeperTestSuite) TestResumeHostZone_UnhaltedZones() {
tc := s.SetupResumeHostZone()

zone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, HostChainId)
s.Require().True(found, "host zone should be in the store")
s.Require().True(zone.Halted, "host zone should be halted")
zone.Halted = false
s.App.StakeibcKeeper.SetHostZone(s.Ctx, zone)

// Set the inner bounds on the host zone
_, err := s.GetMsgServer().ResumeHostZone(s.Ctx, &tc.validMsg)
s.Require().Error(err, "shouldn't be able to call tx on unhalted zones")
expectedErrorMsg := fmt.Sprintf("invalid chain id, zone for %s not halted: host zone is not halted", HostChainId)
s.Require().Equal(expectedErrorMsg, err.Error(), "should return correct error msg")
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@ func (k msgServer) UpdateInnerRedemptionRateBounds(goCtx context.Context, msg *t
zone.MinInnerRedemptionRate = innerMinSafetyThreshold
zone.MaxInnerRedemptionRate = innerMaxSafetyThreshold

// if the redemption rate is within the bounds, unhalt the host zone
if zone.RedemptionRate.GTE(innerMinSafetyThreshold) && zone.RedemptionRate.LTE(innerMaxSafetyThreshold) {
zone.Halted = false
}

k.SetHostZone(ctx, zone)

return &types.MsgUpdateInnerRedemptionRateBoundsResponse{}, nil
Expand Down
2 changes: 2 additions & 0 deletions x/stakeibc/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func RegisterCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgUndelegateHost{}, "stakeibc/UndelegateHost", nil)
cdc.RegisterConcrete(&MsgCalibrateDelegation{}, "stakeibc/CalibrateDelegation", nil)
cdc.RegisterConcrete(&MsgUpdateInnerRedemptionRateBounds{}, "stakeibc/UpdateInnerRedemptionRateBounds", nil)
cdc.RegisterConcrete(&MsgResumeHostZone{}, "stakeibc/ResumeHostZone", nil)
// this line is used by starport scaffolding # 2
}

Expand All @@ -45,6 +46,7 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
&MsgUndelegateHost{},
&MsgCalibrateDelegation{},
&MsgUpdateInnerRedemptionRateBounds{},
&MsgResumeHostZone{},
)

registry.RegisterImplementations((*govtypes.Content)(nil),
Expand Down
1 change: 1 addition & 0 deletions x/stakeibc/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@ var (
ErrUnableToRemoveValidator = errorsmod.Register(ModuleName, 1550, "Unable to remove validator")
ErrUndelegateHostNotCallable = errorsmod.Register(ModuleName, 1551, "Undelegate host is disabled")
ErrInvalidBounds = errorsmod.Register(ModuleName, 1552, "Invalid safety bounds - inner bounds must be within outer bounds")
ErrHostZoneNotHalted = errorsmod.Register(ModuleName, 1553, "host zone is not halted")
)
52 changes: 52 additions & 0 deletions x/stakeibc/types/message_resume_host_zone.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package types

import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/Stride-Labs/stride/v15/utils"
)

const TypeMsgResumeHostZone = "resume_host_zone"

var _ sdk.Msg = &MsgResumeHostZone{}

func NewMsgResumeHostZone(creator string, chainId string) *MsgResumeHostZone {
return &MsgResumeHostZone{
Creator: creator,
ChainId: chainId,
}
}

func (msg *MsgResumeHostZone) Route() string {
return RouterKey
}

func (msg *MsgResumeHostZone) Type() string {
return TypeMsgResumeHostZone
}

func (msg *MsgResumeHostZone) GetSigners() []sdk.AccAddress {
creator, err := sdk.AccAddressFromBech32(msg.Creator)
if err != nil {
panic(err)
}
return []sdk.AccAddress{creator}
}

func (msg *MsgResumeHostZone) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(msg)
return sdk.MustSortJSON(bz)
}

func (msg *MsgResumeHostZone) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(msg.Creator)
if err != nil {
return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err)
}
if err := utils.ValidateAdminAddress(msg.Creator); err != nil {
return err
}
return nil
}
Loading

0 comments on commit 2a0f911

Please sign in to comment.