Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add SetScalingFactorController gov prop #5937

Merged
2 changes: 1 addition & 1 deletion app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers(
AddRoute(txfeestypes.RouterKey, txfees.NewUpdateFeeTokenProposalHandler(*appKeepers.TxFeesKeeper)).
AddRoute(superfluidtypes.RouterKey, superfluid.NewSuperfluidProposalHandler(*appKeepers.SuperfluidKeeper, *appKeepers.EpochsKeeper, *appKeepers.GAMMKeeper)).
AddRoute(protorevtypes.RouterKey, protorev.NewProtoRevProposalHandler(*appKeepers.ProtoRevKeeper)).
AddRoute(gammtypes.RouterKey, gamm.NewMigrationRecordHandler(*appKeepers.GAMMKeeper)).
AddRoute(gammtypes.RouterKey, gamm.NewGammProposalHandler(*appKeepers.GAMMKeeper)).
AddRoute(concentratedliquiditytypes.RouterKey, concentratedliquidity.NewConcentratedLiquidityProposalHandler(*appKeepers.ConcentratedLiquidityKeeper)).
AddRoute(cosmwasmpooltypes.RouterKey, cosmwasmpool.NewCosmWasmPoolProposalHandler(*appKeepers.CosmwasmPoolKeeper))

Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -950,10 +950,6 @@ github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:Ylmch
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3/go.mod h1:lV6KnqXYD/ayTe7310MHtM3I2q8Z6bBfMAi+bhwPYtI=
github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230629191111-f375469de8b6 h1:Kmkx5Rh72+LB8AL6dc6fZA+IVR0INu0YIiMF2ScDhaQ=
github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230629191111-f375469de8b6/go.mod h1:JTym95/bqrSnG5MPcXr1YDhv43JdCeo3p+iDbazoX68=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230709024311-81c831b050de h1:W2lMduMgpNA5zheEIIialw08n1pWJ44Y4t2F924tpDU=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230709024311-81c831b050de/go.mod h1:Pl8Nzx6O6ow/+aqfMoMSz4hX+zz6RrnDYsooptECGxM=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230715164027-b45d8bd42434 h1:MXPrA3sDtqOHYUa9zl4HMGMW+IJwGMqUf6+Hl9nhrCA=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230715164027-b45d8bd42434/go.mod h1:Pl8Nzx6O6ow/+aqfMoMSz4hX+zz6RrnDYsooptECGxM=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230728163612-426afac90c44 h1:UOaBVxEMMv2FS1znU7kHBdtSeZQIjnmXL4r9r19XyBo=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230728163612-426afac90c44/go.mod h1:Pl8Nzx6O6ow/+aqfMoMSz4hX+zz6RrnDYsooptECGxM=
github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304 h1:RIrWLzIiZN5Xd2JOfSOtGZaf6V3qEQYg6EaDTAkMnCo=
Expand Down
15 changes: 15 additions & 0 deletions proto/osmosis/gamm/v1beta1/gov.proto
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,18 @@ message UpdateMigrationRecordsProposal {
repeated BalancerToConcentratedPoolLink records = 3
[ (gogoproto.nullable) = false ];
}

// SetScalingFactorControllerProposal is a gov Content type for updating the
// scaling factor controller address of a stableswap pool
message SetScalingFactorControllerProposal {
option (gogoproto.equal) = true;
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;
option (amino.name) = "osmosis/SetScalingFactorControllerProposal";
option (cosmos_proto.implements_interface) = "cosmos.gov.v1beta1.Content";

string title = 1;
string description = 2;
uint64 pool_id = 3;
string controller_address = 4;
}
12 changes: 10 additions & 2 deletions x/gamm/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ import (
"github.com/osmosis-labs/osmosis/v17/x/gamm/types"
)

// NewMigrationRecordHandler is a handler for governance proposals on new migration records.
func NewMigrationRecordHandler(k keeper.Keeper) govtypes.Handler {
// NewGammProposalHandler is a handler for governance proposals on new migration records.
sampocs marked this conversation as resolved.
Show resolved Hide resolved
func NewGammProposalHandler(k keeper.Keeper) govtypes.Handler {
return func(ctx sdk.Context, content govtypes.Content) error {
switch c := content.(type) {
case *types.UpdateMigrationRecordsProposal:
return handleUpdateMigrationRecordsProposal(ctx, k, c)
case *types.ReplaceMigrationRecordsProposal:
return handleReplaceMigrationRecordsProposal(ctx, k, c)
case *types.SetScalingFactorControllerProposal:
return handleSetScalingFactorControllerProposal(ctx, k, c)

default:
return errorsmod.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized migration record proposal content type: %T", c)
Expand All @@ -35,3 +37,9 @@ func handleReplaceMigrationRecordsProposal(ctx sdk.Context, k keeper.Keeper, p *
func handleUpdateMigrationRecordsProposal(ctx sdk.Context, k keeper.Keeper, p *types.UpdateMigrationRecordsProposal) error {
return k.HandleUpdateMigrationRecordsProposal(ctx, p)
}

// handleSetScalingFactorControllerProposal is a handler for gov proposals to set a stableswap pool's
// scaling factor controller address
func handleSetScalingFactorControllerProposal(ctx sdk.Context, k keeper.Keeper, p *types.SetScalingFactorControllerProposal) error {
return k.HandleSetScalingFactorControllerProposal(ctx, p)
}
4 changes: 4 additions & 0 deletions x/gamm/keeper/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ func (k Keeper) SetStableSwapScalingFactors(ctx sdk.Context, poolId uint64, scal
return k.setStableSwapScalingFactors(ctx, poolId, scalingFactors, sender)
}

func (k Keeper) SetStableSwapScalingFactorController(ctx sdk.Context, poolId uint64, controllerAddress string) error {
return k.setStableSwapScalingFactorController(ctx, poolId, controllerAddress)
}

func AsCFMMPool(pool poolmanagertypes.PoolI) (types.CFMMPoolI, error) {
return asCFMMPool(pool)
}
Expand Down
4 changes: 4 additions & 0 deletions x/gamm/keeper/gov.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ func (k Keeper) HandleReplaceMigrationRecordsProposal(ctx sdk.Context, p *types.
func (k Keeper) HandleUpdateMigrationRecordsProposal(ctx sdk.Context, p *types.UpdateMigrationRecordsProposal) error {
return k.UpdateMigrationRecords(ctx, p.Records)
}

func (k Keeper) HandleSetScalingFactorControllerProposal(ctx sdk.Context, p *types.SetScalingFactorControllerProposal) error {
return k.setStableSwapScalingFactorController(ctx, p.PoolId, p.ControllerAddress)
}
17 changes: 17 additions & 0 deletions x/gamm/keeper/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,23 @@ func (k Keeper) setStableSwapScalingFactors(ctx sdk.Context, poolId uint64, scal
return k.setPool(ctx, stableswapPool)
}

// setStableSwapScalingFactorController updates the scaling factor controller address for a stable swap pool
// errors if the pool does not exist or is not a stable swap pool
func (k Keeper) setStableSwapScalingFactorController(ctx sdk.Context, poolId uint64, controllerAddress string) error {
pool, err := k.GetPoolAndPoke(ctx, poolId)
if err != nil {
return err
}
stableswapPool, ok := pool.(*stableswap.Pool)
if !ok {
return fmt.Errorf("pool id %d is not of type stableswap pool", poolId)
}

stableswapPool.ScalingFactorController = controllerAddress

return k.setPool(ctx, stableswapPool)
}

// asCFMMPool converts PoolI to CFMMPoolI by casting the input.
// Returns the pool of the CFMMPoolI or error if the given pool does not implement
// CFMMPoolI.
Expand Down
77 changes: 77 additions & 0 deletions x/gamm/keeper/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,83 @@ func (s *KeeperTestSuite) TestSetStableSwapScalingFactors() {
}
}

func (s *KeeperTestSuite) TestSetStableSwapScalingFactorController() {
initialControllerAddr := s.TestAccs[0].String()
updatedControllerAddr := s.TestAccs[1].String()

testcases := []struct {
name string
poolId uint64
expError error
isStableSwapPool bool
}{
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets add a test case where we try to use an invalid address as the controller addr

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the address validation happens upstream in ValidateBasic. Want me to duplicate the check here as well?

name: "Error: Pool does not exist",
poolId: 2,
expError: types.PoolDoesNotExistError{PoolId: defaultPoolId + 1},
isStableSwapPool: false,
},
{
name: "Error: Pool id is not of type stableswap pool",
poolId: 1,
expError: fmt.Errorf("pool id 1 is not of type stableswap pool"),
isStableSwapPool: false,
},
{
name: "Valid case",
poolId: 1,
isStableSwapPool: true,
},
}
for _, tc := range testcases {
s.Run(tc.name, func() {
s.SetupTest()
if tc.isStableSwapPool == true {
poolId := s.prepareCustomStableswapPool(
defaultAcctFunds,
stableswap.PoolParams{
SwapFee: defaultSpreadFactor,
ExitFee: defaultZeroExitFee,
},
sdk.NewCoins(sdk.NewCoin(defaultAcctFunds[0].Denom, defaultAcctFunds[0].Amount.QuoRaw(2)), sdk.NewCoin(defaultAcctFunds[1].Denom, defaultAcctFunds[1].Amount.QuoRaw(2))),
[]uint64{1, 1},
)
pool, _ := s.App.GAMMKeeper.GetPoolAndPoke(s.Ctx, poolId)
stableswapPool, _ := pool.(*stableswap.Pool)
stableswapPool.ScalingFactorController = initialControllerAddr
err := s.App.GAMMKeeper.SetPool(s.Ctx, stableswapPool)
s.Require().NoError(err)

// attempt to adjust the scaling factor from the new address - it should fail
err = s.App.GAMMKeeper.SetStableSwapScalingFactors(s.Ctx, tc.poolId, []uint64{1, 2}, updatedControllerAddr)
s.Require().ErrorIs(err, types.ErrNotScalingFactorGovernor)
} else {
s.prepareCustomBalancerPool(
defaultAcctFunds,
defaultPoolAssets,
defaultPoolParams)
}

err := s.App.GAMMKeeper.SetStableSwapScalingFactorController(s.Ctx, tc.poolId, updatedControllerAddr)
if tc.expError != nil {
s.Require().Error(err)
s.Require().EqualError(err, tc.expError.Error())
} else {
s.Require().NoError(err)

// confirm the scaling factor controller has been updated
pool, _ := s.App.GAMMKeeper.GetPoolAndPoke(s.Ctx, tc.poolId)
stableswapPool, _ := pool.(*stableswap.Pool)
s.Require().Equal(updatedControllerAddr, stableswapPool.ScalingFactorController)

// confirm the new controller can update the scaling factor
err = s.App.GAMMKeeper.SetStableSwapScalingFactors(s.Ctx, tc.poolId, []uint64{1, 2}, updatedControllerAddr)
s.Require().NoError(err)
}
})
}
}

func (suite *KeeperTestSuite) TestGetMaximalNoSwapLPAmount() {
tests := map[string]struct {
poolId uint64
Expand Down
61 changes: 59 additions & 2 deletions x/gamm/types/gov.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import (
"fmt"
"strings"

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

govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"

gammmigration "github.com/osmosis-labs/osmosis/v17/x/gamm/types/migration"
)

const (
ProposalTypeUpdateMigrationRecords = "UpdateMigrationRecords"
ProposalTypeReplaceMigrationRecords = "ReplaceMigrationRecords"
ProposalTypeUpdateMigrationRecords = "UpdateMigrationRecords"
ProposalTypeReplaceMigrationRecords = "ReplaceMigrationRecords"
ProposalTypeSetScalingFactorController = "SetScalingFactorController"
)

// Init registers proposals to update and replace migration records.
Expand All @@ -19,11 +23,14 @@ func init() {
govtypes.RegisterProposalTypeCodec(&UpdateMigrationRecordsProposal{}, "osmosis/UpdateMigrationRecordsProposal")
govtypes.RegisterProposalType(ProposalTypeReplaceMigrationRecords)
govtypes.RegisterProposalTypeCodec(&ReplaceMigrationRecordsProposal{}, "osmosis/ReplaceMigrationRecordsProposal")
govtypes.RegisterProposalType(ProposalTypeSetScalingFactorController)
govtypes.RegisterProposalTypeCodec(&SetScalingFactorControllerProposal{}, "osmosis/SetScalingFactorControllerProposal")
}

var (
_ govtypes.Content = &UpdateMigrationRecordsProposal{}
_ govtypes.Content = &ReplaceMigrationRecordsProposal{}
_ govtypes.Content = &SetScalingFactorControllerProposal{}
)

// NewReplacePoolIncentivesProposal returns a new instance of a replace migration record's proposal struct.
Expand Down Expand Up @@ -130,3 +137,53 @@ func (p UpdateMigrationRecordsProposal) String() string {
`, p.Title, p.Description, recordsStr))
return b.String()
}

// NewSetScalingFactorControllerProposal returns a new instance of a replace migration record's proposal struct.
func NewSetScalingFactorControllerProposal(title, description string, poolId uint64, controllerAddress string) govtypes.Content {
return &SetScalingFactorControllerProposal{
Title: title,
Description: description,
PoolId: poolId,
ControllerAddress: controllerAddress,
}
}

// GetTitle gets the title of the proposal
func (p *SetScalingFactorControllerProposal) GetTitle() string { return p.Title }

// GetDescription gets the description of the proposal
func (p *SetScalingFactorControllerProposal) GetDescription() string { return p.Description }

// ProposalRoute returns the router key for the proposal
func (p *SetScalingFactorControllerProposal) ProposalRoute() string { return RouterKey }

// ProposalType returns the type of the proposal
func (p *SetScalingFactorControllerProposal) ProposalType() string {
return ProposalTypeReplaceMigrationRecords
}

// ValidateBasic validates a governance proposal's abstract and basic contents
func (p *SetScalingFactorControllerProposal) ValidateBasic() error {
err := govtypes.ValidateAbstract(p)
if err != nil {
return err
}
_, err = sdk.AccAddressFromBech32(p.ControllerAddress)
if err != nil {
return fmt.Errorf("Invalid controller address (%s)", err)
}

return nil
}

// String returns a string containing the migration record's proposal.
func (p SetScalingFactorControllerProposal) String() string {
var b strings.Builder
b.WriteString(fmt.Sprintf(`Set Scaling Factor Controller Address Proposal:
Title: %s
Description: %s
PoolId: %d
ControllerAddress: %s
`, p.Title, p.Description, p.PoolId, p.ControllerAddress))
return b.String()
}
Loading