Skip to content

Commit

Permalink
feat(rollapp): option to transfer rollapp owner (#1039)
Browse files Browse the repository at this point in the history
  • Loading branch information
zale144 authored Aug 7, 2024
1 parent 55a7517 commit ce6f078
Show file tree
Hide file tree
Showing 23 changed files with 853 additions and 152 deletions.
2 changes: 1 addition & 1 deletion app/upgrades/v4/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func ConvertOldRollappToNew(oldRollapp rollapptypes.Rollapp) rollapptypes.Rollap
alias := strings.Split(oldRollapp.RollappId, "_")[0]
return rollapptypes.Rollapp{
RollappId: oldRollapp.RollappId,
Creator: oldRollapp.Creator,
Owner: oldRollapp.Owner,
GenesisState: oldRollapp.GenesisState,
ChannelId: oldRollapp.ChannelId,
Frozen: oldRollapp.Frozen,
Expand Down
2 changes: 1 addition & 1 deletion app/upgrades/v4/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func (s *UpgradeTestSuite) seedRollapps(numRollapps int) []rollapptypes.Rollapp
rollappID := rollappIDFromIdx(i)
rollapp := rollapptypes.Rollapp{
RollappId: rollappID,
Creator: sample.AccAddressFromSecret(rollappID),
Owner: sample.AccAddressFromSecret(rollappID),
GenesisState: rollapptypes.RollappGenesisState{},
ChannelId: fmt.Sprintf("channel-%d", i),
RegisteredDenoms: []string{"denom1", "denom2"},
Expand Down
4 changes: 2 additions & 2 deletions proto/dymensionxyz/dymension/rollapp/rollapp.proto
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ message Rollapp {
// The unique identifier of the rollapp chain.
// The rollapp_id follows the same standard as cosmos chain_id.
string rollapp_id = 1;
// creator is the bech32-encoded address of the rollapp creator.
string creator = 2;
// owner is the bech32-encoded address of the rollapp owner.
string owner = 2;
// field numbers not to be reused
reserved 3 to 6;
// genesis_state is a partial repr of the state the hub can expect the rollapp to be in upon genesis
Expand Down
21 changes: 18 additions & 3 deletions proto/dymensionxyz/dymension/rollapp/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ service Msg {
rpc CreateRollapp(MsgCreateRollapp) returns (MsgCreateRollappResponse);
rpc UpdateRollappInformation(MsgUpdateRollappInformation) returns (MsgUpdateRollappInformationResponse);
rpc UpdateState(MsgUpdateState) returns (MsgUpdateStateResponse);
rpc TransferOwnership(MsgTransferOwnership) returns (MsgTransferOwnershipResponse);
}

// MsgCreateRollapp creates a new rollapp chain on the hub.
Expand Down Expand Up @@ -47,9 +48,9 @@ message MsgCreateRollappResponse {

// MsgUpdateRollappInformation updates the rollapp information.
message MsgUpdateRollappInformation {
option (cosmos.msg.v1.signer) = "creator";
// creator is the bech32-encoded address of the rollapp creator
string creator = 1;
option (cosmos.msg.v1.signer) = "owner";
// owner is the bech32-encoded address of the rollapp owner
string owner = 1;
// rollapp_id is the unique identifier of the rollapp chain.
string rollapp_id = 2;
// initial_sequencer is one or more bech32-encoded address of the
Expand Down Expand Up @@ -91,3 +92,17 @@ message MsgUpdateState {

message MsgUpdateStateResponse {
}

// MsgTransferOwnership transfers the ownership of a rollapp chain to a new owner.
message MsgTransferOwnership {
option (cosmos.msg.v1.signer) = "current_owner";
// current_owner is the bech32-encoded address of the current owner
string current_owner = 1;
// new_owner is the bech32-encoded address of the new owner
string new_owner = 2;
// rollapp_id is the unique identifier of the rollapp chain.
string rollapp_id = 3;
}

message MsgTransferOwnershipResponse {
}
1 change: 1 addition & 0 deletions x/rollapp/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func GetTxCmd() *cobra.Command {

cmd.AddCommand(CmdCreateRollapp())
cmd.AddCommand(CmdUpdateRollapp())
cmd.AddCommand(CmdTransferOwnership())
cmd.AddCommand(CmdUpdateState())

return cmd
Expand Down
40 changes: 40 additions & 0 deletions x/rollapp/client/cli/tx_transfer_ownership.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
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/dymensionxyz/dymension/v3/x/rollapp/types"
)

func CmdTransferOwnership() *cobra.Command {
cmd := &cobra.Command{
Use: "transfer-ownership [rollapp-id] [new-owner]",
Short: "Transfer ownership of a rollapp to a new owner",
Example: "dymd tx rollapp transfer-ownership ROLLAPP_CHAIN_ID <new_owner_address>",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
// nolint:gofumpt
argRollappId, newOwner := args[0], args[1]

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

msg := types.NewMsgTransferOwnership(
clientCtx.GetFromAddress().String(),
newOwner,
argRollappId,
)

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
2 changes: 1 addition & 1 deletion x/rollapp/keeper/msg_server_create_rollapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ func (suite *RollappTestSuite) createRollappWithCreatorAndVerify(expectedErr err
// rollappExpect is the expected result of creating rollapp
rollappExpect := types.Rollapp{
RollappId: rollapp.GetRollappId(),
Creator: rollapp.GetCreator(),
Owner: rollapp.GetCreator(),
InitialSequencer: rollapp.GetInitialSequencer(),
GenesisChecksum: rollapp.GetGenesisChecksum(),
Bech32Prefix: rollapp.GetBech32Prefix(),
Expand Down
45 changes: 45 additions & 0 deletions x/rollapp/keeper/msg_server_transfer_ownership.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package keeper

import (
"context"
"fmt"

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

"github.com/dymensionxyz/dymension/v3/x/rollapp/types"
)

func (k msgServer) TransferOwnership(goCtx context.Context, msg *types.MsgTransferOwnership) (*types.MsgTransferOwnershipResponse, error) {
if err := msg.ValidateBasic(); err != nil {
return nil, errorsmod.Wrap(types.ErrInvalidRequest, err.Error())
}

ctx := sdk.UnwrapSDKContext(goCtx)

rollapp, ok := k.GetRollapp(ctx, msg.RollappId)
if !ok {
return nil, types.ErrUnknownRollappID
}

if rollapp.Owner != msg.CurrentOwner {
return nil, types.ErrUnauthorizedSigner
}

if rollapp.Frozen {
return nil, types.ErrRollappFrozen
}

if rollapp.Owner == msg.NewOwner {
return nil, types.ErrSameOwner
}

rollapp.Owner = msg.NewOwner
k.SetRollapp(ctx, rollapp)

if err := ctx.EventManager().EmitTypedEvent(msg); err != nil {
return nil, fmt.Errorf("emit event: %w", err)
}

return &types.MsgTransferOwnershipResponse{}, nil
}
101 changes: 101 additions & 0 deletions x/rollapp/keeper/msg_server_transfer_ownership_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package keeper_test

import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/dymensionxyz/dymension/v3/x/rollapp/types"
)

func (suite *RollappTestSuite) TestTransferOwnership() {
const rollappId = "rollapp_1234-1"

tests := []struct {
name string
request *types.MsgTransferOwnership
malleate func(rollapp types.Rollapp) types.Rollapp
expError error
expRollapp types.Rollapp
}{
{
name: "Transfer rollapp ownership: success",
request: types.NewMsgTransferOwnership(
alice, bob, rollappId,
),
expError: nil,
expRollapp: types.Rollapp{
Owner: bob,
RollappId: rollappId,
},
}, {
name: "Transfer rollapp ownership: failed, rollapp not found",
request: types.NewMsgTransferOwnership(
alice, bob, "rollapp_1235-2",
),
expError: types.ErrUnknownRollappID,
}, {
name: "Transfer rollapp ownership: failed, same owner",
request: types.NewMsgTransferOwnership(
alice, alice, rollappId,
),
expError: types.ErrSameOwner,
}, {
name: "Transfer rollapp ownership: failed, unauthorized signer",
request: types.NewMsgTransferOwnership(
bob, alice, rollappId,
),
expError: types.ErrUnauthorizedSigner,
}, {
name: "Transfer rollapp ownership: failed, frozen rollapp",
request: types.NewMsgTransferOwnership(
alice, bob, rollappId,
),
malleate: func(rollapp types.Rollapp) types.Rollapp {
rollapp.Frozen = true
return rollapp
},
expError: types.ErrRollappFrozen,
}, {
name: "Transfer rollapp ownership: failed, invalid current owner address",
request: types.NewMsgTransferOwnership(
"invalid_address", bob, rollappId,
),
expError: types.ErrInvalidRequest,
}, {
name: "Transfer rollapp ownership: failed, invalid new owner address",
request: types.NewMsgTransferOwnership(
alice, "invalid_address", rollappId,
),
expError: types.ErrInvalidRequest,
},
}

for _, tc := range tests {
suite.Run(tc.name, func() {
suite.SetupTest()

rollapp := types.Rollapp{
RollappId: rollappId,
Owner: alice,
Frozen: false,
Sealed: false,
}

if tc.malleate != nil {
rollapp = tc.malleate(rollapp)
}

suite.App.RollappKeeper.SetRollapp(suite.Ctx, rollapp)

goCtx := sdk.WrapSDKContext(suite.Ctx)
_, err := suite.msgServer.TransferOwnership(goCtx, tc.request)
if tc.expError == nil {
suite.Require().NoError(err)
resp, err := suite.queryClient.Rollapp(goCtx, &types.QueryGetRollappRequest{RollappId: tc.request.RollappId})
suite.Require().NoError(err)
suite.Equal(tc.expRollapp, resp.Rollapp)
} else {
suite.ErrorIs(err, tc.expError)
}
})
}
}
28 changes: 14 additions & 14 deletions x/rollapp/keeper/msg_server_update_rollapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (suite *RollappTestSuite) TestUpdateRollapp() {
{
name: "Update rollapp: success",
update: &types.MsgUpdateRollappInformation{
Creator: alice,
Owner: alice,
RollappId: rollappId,
InitialSequencer: initialSequencerAddress,
Alias: "rolly",
Expand All @@ -37,7 +37,7 @@ func (suite *RollappTestSuite) TestUpdateRollapp() {
},
expError: nil,
expRollapp: types.Rollapp{
Creator: alice,
Owner: alice,
RollappId: rollappId,
InitialSequencer: initialSequencerAddress,
Bech32Prefix: "rol",
Expand All @@ -49,23 +49,23 @@ func (suite *RollappTestSuite) TestUpdateRollapp() {
}, {
name: "Update rollapp: fail - try to update a non-existing rollapp",
update: &types.MsgUpdateRollappInformation{
Creator: alice,
Owner: alice,
RollappId: "somerollapp_1235-1",
InitialSequencer: initialSequencerAddress,
},
expError: gerrc.ErrNotFound,
}, {
name: "Update rollapp: fail - try to update from non-creator address",
update: &types.MsgUpdateRollappInformation{
Creator: bob,
Owner: bob,
RollappId: rollappId,
InitialSequencer: initialSequencerAddress,
},
expError: sdkerrors.ErrUnauthorized,
}, {
name: "Update rollapp: fail - try to update a frozen rollapp",
update: &types.MsgUpdateRollappInformation{
Creator: alice,
Owner: alice,
RollappId: rollappId,
InitialSequencer: initialSequencerAddress,
},
Expand All @@ -74,7 +74,7 @@ func (suite *RollappTestSuite) TestUpdateRollapp() {
}, {
name: "Update rollapp: fail - try to update InitialSequencer when sealed",
update: &types.MsgUpdateRollappInformation{
Creator: alice,
Owner: alice,
RollappId: rollappId,
InitialSequencer: initialSequencerAddress,
},
Expand All @@ -83,7 +83,7 @@ func (suite *RollappTestSuite) TestUpdateRollapp() {
}, {
name: "Update rollapp: fail - try to update alias when sealed",
update: &types.MsgUpdateRollappInformation{
Creator: alice,
Owner: alice,
RollappId: rollappId,
Alias: "rolly",
},
Expand All @@ -92,7 +92,7 @@ func (suite *RollappTestSuite) TestUpdateRollapp() {
}, {
name: "Update rollapp: fail - try to update genesis checksum when sealed",
update: &types.MsgUpdateRollappInformation{
Creator: alice,
Owner: alice,
RollappId: rollappId,
GenesisChecksum: "new_checksum",
},
Expand All @@ -101,15 +101,15 @@ func (suite *RollappTestSuite) TestUpdateRollapp() {
}, {
name: "Update rollapp: success - update metadata when sealed",
update: &types.MsgUpdateRollappInformation{
Creator: alice,
Owner: alice,
RollappId: rollappId,
Metadata: &mockRollappMetadata,
},
sealed: true,
expError: nil,
expRollapp: types.Rollapp{
RollappId: rollappId,
Creator: alice,
Owner: alice,
InitialSequencer: "",
GenesisChecksum: "checksum1",
ChannelId: "",
Expand All @@ -131,7 +131,7 @@ func (suite *RollappTestSuite) TestUpdateRollapp() {
goCtx := sdk.WrapSDKContext(suite.Ctx)
rollapp := types.Rollapp{
RollappId: rollappId,
Creator: alice,
Owner: alice,
InitialSequencer: "",
GenesisChecksum: "checksum1",
ChannelId: "",
Expand Down Expand Up @@ -174,7 +174,7 @@ func (suite *RollappTestSuite) TestCreateAndUpdateRollapp() {
// 1. register rollapp
err := suite.App.RollappKeeper.RegisterRollapp(suite.Ctx, types.Rollapp{
RollappId: rollappId,
Creator: alice,
Owner: alice,
GenesisChecksum: "",
InitialSequencer: "",
Alias: "default",
Expand All @@ -192,7 +192,7 @@ func (suite *RollappTestSuite) TestCreateAndUpdateRollapp() {
addrInit := sdk.AccAddress(initSeqPubKey.Address()).String()

err = suite.App.RollappKeeper.UpdateRollapp(suite.Ctx, &types.MsgUpdateRollappInformation{
Creator: alice,
Owner: alice,
RollappId: rollappId,
InitialSequencer: addrInit,
GenesisChecksum: "checksum1",
Expand All @@ -213,7 +213,7 @@ func (suite *RollappTestSuite) TestCreateAndUpdateRollapp() {

// 5. try to update rollapp immutable fields - should fail because rollapp is sealed
err = suite.App.RollappKeeper.UpdateRollapp(suite.Ctx, &types.MsgUpdateRollappInformation{
Creator: alice,
Owner: alice,
RollappId: rollappId,
Alias: "rolly",
})
Expand Down
Loading

0 comments on commit ce6f078

Please sign in to comment.