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

bypass permissionless concentrated liquidity checks #6420

Merged
merged 17 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions proto/osmosis/concentrated-liquidity/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,11 @@ message Params {
bool is_permissionless_pool_creation_enabled = 6
[ (gogoproto.moretags) =
"yaml:\"is_permissionless_pool_creation_enabled\"" ];

// unrestricted_pool_creator_whitelist is a list of addresses that are
// allowed to bypass restrictions on permissionless supercharged pool
// creation, like pool_creation_enabled, restricted quote assets, no
// double creation of pools, etc.
repeated string unrestricted_pool_creator_whitelist = 7
[ (gogoproto.moretags) = "yaml:\"unrestricted_pool_creator_whitelist\"" ];
p0mvn marked this conversation as resolved.
Show resolved Hide resolved
}
33 changes: 27 additions & 6 deletions x/concentrated-liquidity/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,37 @@ func (k Keeper) InitializePool(ctx sdk.Context, poolI poolmanagertypes.PoolI, cr
quoteAsset := concentratedPool.GetToken1()
poolManagerParams := k.poolmanagerKeeper.GetParams(ctx)

if !k.validateTickSpacing(params, tickSpacing) {
return types.UnauthorizedTickSpacingError{ProvidedTickSpacing: tickSpacing, AuthorizedTickSpacings: params.AuthorizedTickSpacing}
bypassRestrictions := false

poolmanagerModuleAcc := k.accountKeeper.GetModuleAccount(ctx, poolmanagertypes.ModuleName).GetAddress()

// allow pool mananger module account to bypass restrictions (i.e. gov prop)
if creatorAddress.Equals(poolmanagerModuleAcc) {
bypassRestrictions = true
}

if !k.validateSpreadFactor(params, spreadFactor) {
return types.UnauthorizedSpreadFactorError{ProvidedSpreadFactor: spreadFactor, AuthorizedSpreadFactors: params.AuthorizedSpreadFactors}
// allow whitelisted pool creators to bypass restrictions
if !bypassRestrictions {
for _, addr := range params.UnrestrictedPoolCreatorWhitelist {
// okay to use MustAccAddressFromBech32 because already validated in params
if sdk.MustAccAddressFromBech32(addr).Equals(creatorAddress) {
bypassRestrictions = true
}
}
}

if !validateAuthorizedQuoteDenoms(quoteAsset, poolManagerParams.AuthorizedQuoteDenoms) {
return types.UnauthorizedQuoteDenomError{ProvidedQuoteDenom: quoteAsset, AuthorizedQuoteDenoms: poolManagerParams.AuthorizedQuoteDenoms}
if !bypassRestrictions {
if !k.validateTickSpacing(params, tickSpacing) {
return types.UnauthorizedTickSpacingError{ProvidedTickSpacing: tickSpacing, AuthorizedTickSpacings: params.AuthorizedTickSpacing}
}

if !k.validateSpreadFactor(params, spreadFactor) {
return types.UnauthorizedSpreadFactorError{ProvidedSpreadFactor: spreadFactor, AuthorizedSpreadFactors: params.AuthorizedSpreadFactors}
}

if !validateAuthorizedQuoteDenoms(quoteAsset, poolManagerParams.AuthorizedQuoteDenoms) {
return types.UnauthorizedQuoteDenomError{ProvidedQuoteDenom: quoteAsset, AuthorizedQuoteDenoms: poolManagerParams.AuthorizedQuoteDenoms}
}
}

if err := k.createSpreadRewardAccumulator(ctx, poolId); err != nil {
Expand Down
40 changes: 35 additions & 5 deletions x/concentrated-liquidity/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,15 @@ func (s *KeeperTestSuite) TestInitializePool() {

validCreatorAddress := s.TestAccs[0]

poolmanagerModuleAccount := s.App.AccountKeeper.GetModuleAccount(s.Ctx, poolmanagertypes.ModuleName).GetAddress()

tests := []struct {
name string
poolI poolmanagertypes.PoolI
authorizedDenomsOverwrite []string
creatorAddress sdk.AccAddress
expectedErr error
name string
poolI poolmanagertypes.PoolI
authorizedDenomsOverwrite []string
unrestrictedPoolCreatorWhitelist []string
creatorAddress sdk.AccAddress
expectedErr error
}{
{
name: "Happy path",
Expand Down Expand Up @@ -79,6 +82,23 @@ func (s *KeeperTestSuite) TestInitializePool() {
creatorAddress: validCreatorAddress,
expectedErr: types.UnauthorizedQuoteDenomError{ProvidedQuoteDenom: USDC, AuthorizedQuoteDenoms: []string{"otherDenom"}},
},
{
name: "bypass check because poolmanager module account",
poolI: validPoolI,
authorizedDenomsOverwrite: []string{"otherDenom"},
// despite the quote denom not being authorized, will still
// pass because its coming from the poolmanager module account
creatorAddress: poolmanagerModuleAccount,
},
{
name: "bypass check because of whitelisted bypass",
poolI: validPoolI,
authorizedDenomsOverwrite: []string{"otherDenom"},
// despite the quote denom not being authorized, will still
// pass because its coming from a whitelisted pool creator
unrestrictedPoolCreatorWhitelist: []string{validCreatorAddress.String()},
creatorAddress: validCreatorAddress,
},
}

for _, test := range tests {
Expand All @@ -91,6 +111,16 @@ func (s *KeeperTestSuite) TestInitializePool() {
s.App.PoolManagerKeeper.SetParams(s.Ctx, params)
}

if len(test.unrestrictedPoolCreatorWhitelist) > 0 {
params := s.App.ConcentratedLiquidityKeeper.GetParams(s.Ctx)
params.UnrestrictedPoolCreatorWhitelist = test.unrestrictedPoolCreatorWhitelist
fmt.Println("setting")
fmt.Println(params.UnrestrictedPoolCreatorWhitelist)
sunnya97 marked this conversation as resolved.
Show resolved Hide resolved
s.App.ConcentratedLiquidityKeeper.SetParams(s.Ctx, params)
fmt.Println("getting")
fmt.Println(s.App.ConcentratedLiquidityKeeper.GetParams(s.Ctx).UnrestrictedPoolCreatorWhitelist)
Copy link
Member

Choose a reason for hiding this comment

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

nit: prints but I saw them being removed in a follow-up PR so good with keeping them until then

sunnya97 marked this conversation as resolved.
Show resolved Hide resolved
}

s.setListenerMockOnConcentratedLiquidityKeeper()

// Method under test.
Expand Down
3 changes: 2 additions & 1 deletion x/concentrated-liquidity/types/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@ var (
}
DefaultBalancerSharesDiscount = osmomath.MustNewDecFromStr("0.05")
// By default, we only authorize one nanosecond (one block) uptime as an option
DefaultAuthorizedUptimes = []time.Duration{time.Nanosecond}
DefaultAuthorizedUptimes = []time.Duration{time.Nanosecond}
DefaultUnrestrictedPoolCreatorWhitelist = []string{}
)
33 changes: 32 additions & 1 deletion x/concentrated-liquidity/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var (
KeyAuthorizedQuoteDenoms = []byte("AuthorizedQuoteDenoms")
KeyAuthorizedUptimes = []byte("AuthorizedUptimes")
KeyIsPermisionlessPoolCreationEnabled = []byte("IsPermisionlessPoolCreationEnabled")
KeyUnrestrictedPoolCreatorWhitelist = []byte("UnrestrictedPoolCreatorWhitelist")

_ paramtypes.ParamSet = &Params{}
)
Expand All @@ -27,14 +28,15 @@ func ParamKeyTable() paramtypes.KeyTable {
return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
}

func NewParams(authorizedTickSpacing []uint64, authorizedSpreadFactors []osmomath.Dec, discountRate osmomath.Dec, authorizedQuoteDenoms []string, authorizedUptimes []time.Duration, isPermissionlessPoolCreationEnabled bool) Params {
func NewParams(authorizedTickSpacing []uint64, authorizedSpreadFactors []osmomath.Dec, discountRate osmomath.Dec, authorizedQuoteDenoms []string, authorizedUptimes []time.Duration, isPermissionlessPoolCreationEnabled bool, unrestrictedPoolCreatorWhitelist []string) Params {
return Params{
AuthorizedTickSpacing: authorizedTickSpacing,
AuthorizedSpreadFactors: authorizedSpreadFactors,
AuthorizedQuoteDenoms: authorizedQuoteDenoms,
BalancerSharesRewardDiscount: discountRate,
AuthorizedUptimes: authorizedUptimes,
IsPermissionlessPoolCreationEnabled: isPermissionlessPoolCreationEnabled,
UnrestrictedPoolCreatorWhitelist: unrestrictedPoolCreatorWhitelist,
}
}

Expand All @@ -52,6 +54,7 @@ func DefaultParams() Params {
BalancerSharesRewardDiscount: DefaultBalancerSharesDiscount,
AuthorizedUptimes: DefaultAuthorizedUptimes,
IsPermissionlessPoolCreationEnabled: false,
UnrestrictedPoolCreatorWhitelist: DefaultUnrestrictedPoolCreatorWhitelist,
}
}

Expand All @@ -75,6 +78,9 @@ func (p Params) Validate() error {
if err := validateAuthorizedUptimes(p.AuthorizedUptimes); err != nil {
return err
}
if err := validateUnrestrictedPoolCreatorWhitelist(p.UnrestrictedPoolCreatorWhitelist); err != nil {
return err
}
return nil
}

Expand All @@ -87,6 +93,7 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
paramtypes.NewParamSetPair(KeyIsPermisionlessPoolCreationEnabled, &p.IsPermissionlessPoolCreationEnabled, validateIsPermissionLessPoolCreationEnabled),
paramtypes.NewParamSetPair(KeyDiscountRate, &p.BalancerSharesRewardDiscount, validateBalancerSharesDiscount),
paramtypes.NewParamSetPair(KeyAuthorizedUptimes, &p.AuthorizedUptimes, validateAuthorizedUptimes),
paramtypes.NewParamSetPair(KeyUnrestrictedPoolCreatorWhitelist, &p.UnrestrictedPoolCreatorWhitelist, validateUnrestrictedPoolCreatorWhitelist),
}
}

Expand Down Expand Up @@ -235,3 +242,27 @@ func validateAuthorizedUptimes(i interface{}) error {

return nil
}

// validateUnrestrictedPoolCreatorWhitelist validates a slice of addresses
// that are allowed to bypass the restrictions on permissionless pool creation
//
// Parameters:
// - i: The parameter to validate.
//
// Returns:
// - An error if any of the strings are not addresses
func validateUnrestrictedPoolCreatorWhitelist(i interface{}) error {
whitelist, ok := i.([]string)

if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}

for _, a := range whitelist {
if _, err := sdk.AccAddressFromBech32(a); err != nil {
return fmt.Errorf("invalid address")
}
}

return nil
}
134 changes: 98 additions & 36 deletions x/concentrated-liquidity/types/params.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.