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

Create Message for Staking Conversion #5949

Merged
merged 33 commits into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
5f48cb3
WIP
mattverse Aug 2, 2023
2526268
Almost done, need more test cases...
mattverse Aug 3, 2023
9f10685
Finish adding test cases
mattverse Aug 4, 2023
8516a9b
Use val set
mattverse Aug 4, 2023
4986e0e
Add changelog
mattverse Aug 4, 2023
18e8898
Merge branch 'main' into mattverse/stake-multi0msg
devbot-wizard Aug 7, 2023
6000313
Fix simple problems
devbot-wizard Aug 7, 2023
343be73
Update tx.pb.go
ValarDragon Aug 7, 2023
1bef463
Remove partial unlocking
mattverse Aug 8, 2023
0898bdc
Use val set delegation and edit test cases
mattverse Aug 8, 2023
acd179e
Update proto/osmosis/superfluid/tx.proto
mattverse Aug 8, 2023
693c4e2
Update x/superfluid/keeper/stake.go
mattverse Aug 8, 2023
be4c03a
Romans comment, add balancer check
mattverse Aug 8, 2023
c89e9c3
Adam's comment
mattverse Aug 8, 2023
23f53c3
Change errors from bool to check error
mattverse Aug 8, 2023
b953043
Merge branch 'main' into mattverse/stake-multi0msg
czarcas7ic Aug 8, 2023
0c5b652
Add validate basic, bring back partial share migration for liquid gam…
mattverse Aug 9, 2023
69f6b39
Try abstracting check logics from test
mattverse Aug 9, 2023
06d1231
Merge branch 'main' into mattverse/stake-multi0msg
mattverse Aug 9, 2023
96f486b
Romans comment
mattverse Aug 10, 2023
306a955
Merge branch 'main' into mattverse/stake-multi0msg
mattverse Aug 10, 2023
ba1d943
Add cli
mattverse Aug 10, 2023
c8b9f31
Fix cli
mattverse Aug 10, 2023
0e9eeb1
Update x/superfluid/keeper/stake.go
czarcas7ic Aug 10, 2023
97c80f2
Update x/superfluid/client/cli/tx.go
czarcas7ic Aug 10, 2023
a2ad24b
Update x/superfluid/keeper/stake.go
czarcas7ic Aug 10, 2023
18f4bd7
Roman and Adam
mattverse Aug 11, 2023
d7e9511
Fix merge conflict
mattverse Aug 11, 2023
e5a054c
Update x/superfluid/keeper/stake.go
czarcas7ic Aug 11, 2023
33ac505
fix merge conflict
mattverse Aug 12, 2023
fe4b64c
Adams comment
mattverse Aug 12, 2023
c7b9fdb
Update x/superfluid/keeper/stake.go
mattverse Aug 14, 2023
9244686
Romans comments
mattverse Aug 14, 2023
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#5874](https://github.com/osmosis-labs/osmosis/pull/5874) Remove Partial Migration from superfluid migration to CL
* [#5901](https://github.com/osmosis-labs/osmosis/pull/5901) Adding support for CW pools in ProtoRev
* [#5937](https://github.com/osmosis-labs/osmosis/pull/5937) feat: add SetScalingFactorController gov prop
* [#5949](https://github.com/osmosis-labs/osmosis/pull/5949) Add message to convert from superfluid / locks to native staking directly.
* [#5939](https://github.com/osmosis-labs/osmosis/pull/5939) Fix: Flip existing twapRecords base/quote price denoms
* [#5938](https://github.com/osmosis-labs/osmosis/pull/5938) Chore: Fix valset amino codec

Expand Down
10 changes: 5 additions & 5 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,11 +394,6 @@ func (appKeepers *AppKeepers) InitNormalKeepers(
appKeepers.ConcentratedLiquidityKeeper.SetIncentivesKeeper(appKeepers.IncentivesKeeper)
appKeepers.GAMMKeeper.SetIncentivesKeeper(appKeepers.IncentivesKeeper)

appKeepers.SuperfluidKeeper = superfluidkeeper.NewKeeper(
appKeepers.keys[superfluidtypes.StoreKey], appKeepers.GetSubspace(superfluidtypes.ModuleName),
*appKeepers.AccountKeeper, appKeepers.BankKeeper, appKeepers.StakingKeeper, appKeepers.DistrKeeper, appKeepers.EpochsKeeper, appKeepers.LockupKeeper, appKeepers.GAMMKeeper, appKeepers.IncentivesKeeper,
lockupkeeper.NewMsgServerImpl(appKeepers.LockupKeeper), appKeepers.ConcentratedLiquidityKeeper)

mintKeeper := mintkeeper.NewKeeper(
appKeepers.keys[minttypes.StoreKey],
appKeepers.GetSubspace(minttypes.ModuleName),
Expand Down Expand Up @@ -446,6 +441,11 @@ func (appKeepers *AppKeepers) InitNormalKeepers(

appKeepers.ValidatorSetPreferenceKeeper = &validatorSetPreferenceKeeper

appKeepers.SuperfluidKeeper = superfluidkeeper.NewKeeper(
mattverse marked this conversation as resolved.
Show resolved Hide resolved
appKeepers.keys[superfluidtypes.StoreKey], appKeepers.GetSubspace(superfluidtypes.ModuleName),
*appKeepers.AccountKeeper, appKeepers.BankKeeper, appKeepers.StakingKeeper, appKeepers.DistrKeeper, appKeepers.EpochsKeeper, appKeepers.LockupKeeper, appKeepers.GAMMKeeper, appKeepers.IncentivesKeeper,
lockupkeeper.NewMsgServerImpl(appKeepers.LockupKeeper), appKeepers.ConcentratedLiquidityKeeper, appKeepers.PoolManagerKeeper, appKeepers.ValidatorSetPreferenceKeeper)

// The last arguments can contain custom message handlers, and custom query handlers,
// if we want to allow any custom callbacks
supportedFeatures := "iterator,staking,stargate,osmosis,cosmwasm_1_1,cosmwasm_1_2"
Expand Down
41 changes: 41 additions & 0 deletions proto/osmosis/superfluid/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ service Msg {
rpc AddToConcentratedLiquiditySuperfluidPosition(
MsgAddToConcentratedLiquiditySuperfluidPosition)
returns (MsgAddToConcentratedLiquiditySuperfluidPositionResponse);

// UnbondConvertAndStake breaks all locks / superfluid staked assets,
// converts them to osmo then stakes the osmo to the designated validator.
rpc UnbondConvertAndStake(MsgUnbondConvertAndStake)
returns (MsgUnbondConvertAndStakeResponse);
}

message MsgSuperfluidDelegate {
Expand Down Expand Up @@ -231,4 +236,40 @@ message MsgAddToConcentratedLiquiditySuperfluidPositionResponse {
(gogoproto.nullable) = false
];
uint64 lock_id = 4 [ (gogoproto.moretags) = "yaml:\"lock_id\"" ];
}

// ===================== MsgUnbondConvertAndStake
message MsgUnbondConvertAndStake {
option (amino.name) = "osmosis/unbond-convert-and-stake";

// lock ID to convert and stake.
// lock id with 0 should be provided if converting liquid gamm shares to stake
uint64 lock_id = 1 [ (gogoproto.moretags) = "yaml:\"lock_id\"" ];
string sender = 2 [ (gogoproto.moretags) = "yaml:\"sender\"" ];
// validator address to delegate to.
// If provided empty string, we use the validators returned from
// valset-preference module.
string val_addr = 3;
czarcas7ic marked this conversation as resolved.
Show resolved Hide resolved
// min_amt_to_stake indicates the minimum amount to stake after conversion
string min_amt_to_stake = 4 [
mattverse marked this conversation as resolved.
Show resolved Hide resolved
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"min_amt_to_stake\"",
(gogoproto.nullable) = false
];
// shares_to_convert indicates shares wanted to stake.
// Note that this field is only used for liquid(unlocked) gamm shares.
// For all other cases, this field would be disregarded.
cosmos.base.v1beta1.Coin shares_to_convert = 5 [
(gogoproto.nullable) = false,
(gogoproto.moretags) = "yaml:\"shares_to_convert\"",
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coin"
];
Comment on lines +259 to +266
Copy link
Member

Choose a reason for hiding this comment

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

This does read as maybe we should have two different messages, but perhaps lets save that for a subsequent PR?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah tbh I feel the same way, down to make an issue once this get merged

}

message MsgUnbondConvertAndStakeResponse {
string total_amt_staked = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"total_amt_staked\"",
(gogoproto.nullable) = false
];
}
54 changes: 54 additions & 0 deletions x/superfluid/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func GetTxCmd() *cobra.Command {
// NewSuperfluidRedelegateCmd(),
NewCmdLockAndSuperfluidDelegate(),
NewCmdUnPoolWhitelistedPool(),
NewUnbondConvertAndStake(),
)
osmocli.AddTxCmd(cmd, NewCreateFullRangePositionAndSuperfluidDelegateCmd)
osmocli.AddTxCmd(cmd, NewAddToConcentratedLiquiditySuperfluidPositionCmd)
Expand Down Expand Up @@ -423,3 +424,56 @@ func NewUnlockAndMigrateSharesToFullRangeConcentratedPositionCmd() (*osmocli.TxC
Example: "unlock-and-migrate-cl 10 25000000000gamm/pool/2 1000000000uosmo,10000000uion",
}, &types.MsgUnlockAndMigrateSharesToFullRangeConcentratedPosition{}
}

func NewUnbondConvertAndStake() *cobra.Command {
cmd := &cobra.Command{
Use: "unbond-convert-and-stake [lock-id] [valAddr] [min-amount-to-stake](optional) [shares-to-convert](optional)",
Short: "instantly unbond any locked gamm shares convert them into osmo and stake",
Example: "unbond-convert-and-stake 10 osmo1xxx 100000uosmo",
Args: cobra.MinimumNArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

txf := tx.NewFactoryCLI(clientCtx, cmd.Flags()).WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever)

sender := clientCtx.GetFromAddress()
lockId, err := strconv.Atoi(args[0])
if err != nil {
return err
}

valAddr := args[1]

var minAmtToStake sdk.Int
// if user provided args for min amount to stake, use it. If not, use empty coin struct
var sharesToConvert sdk.Coin
if len(args) >= 3 {
convertedInt, ok := sdk.NewIntFromString(args[2])
if !ok {
return fmt.Errorf("Conversion for sdk.Int failed")
}
minAmtToStake = convertedInt
if len(args) == 4 {
coins, err := sdk.ParseCoinNormalized(args[3])
if err != nil {
return err
}
sharesToConvert = coins
}
} else {
minAmtToStake = sdk.ZeroInt()
sharesToConvert = sdk.Coin{}
}

msg := types.NewMsgUnbondConvertAndStake(sender, uint64(lockId), valAddr, minAmtToStake, sharesToConvert)

return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg)
},
}

flags.AddTxFlagsToCmd(cmd)
return cmd
}
30 changes: 26 additions & 4 deletions x/superfluid/keeper/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ func (k Keeper) MigrateNonSuperfluidLockBalancerToConcentrated(ctx sdk.Context,
return k.migrateNonSuperfluidLockBalancerToConcentrated(ctx, sender, lockId, sharesToMigrate, tokenOutMins)
}

func (k Keeper) ValidateSharesToMigrateUnlockAndExitBalancerPool(ctx sdk.Context, sender sdk.AccAddress, poolIdLeaving uint64, lock *lockuptypes.PeriodLock, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins) (exitCoins sdk.Coins, err error) {
return k.validateSharesToMigrateUnlockAndExitBalancerPool(ctx, sender, poolIdLeaving, lock, sharesToMigrate, tokenOutMins)
func (k Keeper) ForceUnlockAndExitBalancerPool(ctx sdk.Context, sender sdk.AccAddress, poolIdLeaving uint64, lock *lockuptypes.PeriodLock, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins, exitCoinsLengthIsTwo bool) (exitCoins sdk.Coins, err error) {
return k.forceUnlockAndExitBalancerPool(ctx, sender, poolIdLeaving, lock, sharesToMigrate, tokenOutMins, exitCoinsLengthIsTwo)
}

func (k Keeper) RouteMigration(ctx sdk.Context, sender sdk.AccAddress, lockId int64, sharesToMigrate sdk.Coin) (synthLockBeforeMigration lockuptypes.SyntheticLock, migrationType MigrationType, err error) {
return k.routeMigration(ctx, sender, lockId, sharesToMigrate)
func (k Keeper) GetMigrationType(ctx sdk.Context, sender sdk.AccAddress, lockId int64) (synthLockBeforeMigration lockuptypes.SyntheticLock, migrationType MigrationType, err error) {
return k.getMigrationType(ctx, sender, lockId)
}

func (k Keeper) ValidateMigration(ctx sdk.Context, sender sdk.AccAddress, lockId uint64, sharesToMigrate sdk.Coin) (types.MigrationPoolIDs, *lockuptypes.PeriodLock, time.Duration, error) {
Expand All @@ -62,3 +62,25 @@ func (k Keeper) GetExistingLockRemainingDuration(ctx sdk.Context, lock *lockupty
func (k Keeper) DistributeSuperfluidGauges(ctx sdk.Context) {
k.distributeSuperfluidGauges(ctx)
}

func (k Keeper) ConvertLockToStake(ctx sdk.Context, sender sdk.AccAddress, valAddr string, lockId uint64,
minAmtToStake sdk.Int) (totalAmtConverted sdk.Int, err error) {
return k.convertLockToStake(ctx, sender, valAddr, lockId, minAmtToStake)
}

func (k Keeper) ConvertGammSharesToOsmoAndStake(
ctx sdk.Context,
sender sdk.AccAddress, valAddr string,
poolIdLeaving uint64, exitCoins sdk.Coins, minAmtToStake sdk.Int, originalSuperfluidValAddr string,
) (totalAmtCoverted sdk.Int, err error) {
return k.convertGammSharesToOsmoAndStake(ctx, sender, valAddr, poolIdLeaving, exitCoins, minAmtToStake, originalSuperfluidValAddr)
}

func (k Keeper) ConvertUnlockedToStake(ctx sdk.Context, sender sdk.AccAddress, valAddr string, sharesToStake sdk.Coin,
minAmtToStake sdk.Int) (totalAmtConverted sdk.Int, err error) {
return k.convertUnlockedToStake(ctx, sender, valAddr, sharesToStake, minAmtToStake)
}

func (k Keeper) DelegateBaseOnValsetPref(ctx sdk.Context, sender sdk.AccAddress, valAddr, originalSuperfluidValAddr string, totalAmtToStake sdk.Int) error {
return k.delegateBaseOnValsetPref(ctx, sender, valAddr, originalSuperfluidValAddr, totalAmtToStake)
}
24 changes: 14 additions & 10 deletions x/superfluid/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,25 @@ type Keeper struct {
storeKey sdk.StoreKey
paramSpace paramtypes.Subspace

ak authkeeper.AccountKeeper
bk types.BankKeeper
sk types.StakingKeeper
ck types.CommunityPoolKeeper
ek types.EpochKeeper
lk types.LockupKeeper
gk types.GammKeeper
ik types.IncentivesKeeper
clk types.ConcentratedKeeper
ak authkeeper.AccountKeeper
bk types.BankKeeper
sk types.StakingKeeper
ck types.CommunityPoolKeeper
ek types.EpochKeeper
lk types.LockupKeeper
gk types.GammKeeper
ik types.IncentivesKeeper
clk types.ConcentratedKeeper
pmk types.PoolManagerKeeper
vspk types.ValSetPreferenceKeeper

lms types.LockupMsgServer
}

var _ govtypes.StakingKeeper = (*Keeper)(nil)

// NewKeeper returns an instance of Keeper.
func NewKeeper(storeKey sdk.StoreKey, paramSpace paramtypes.Subspace, ak authkeeper.AccountKeeper, bk types.BankKeeper, sk types.StakingKeeper, dk types.CommunityPoolKeeper, ek types.EpochKeeper, lk types.LockupKeeper, gk types.GammKeeper, ik types.IncentivesKeeper, lms types.LockupMsgServer, clk types.ConcentratedKeeper) *Keeper {
func NewKeeper(storeKey sdk.StoreKey, paramSpace paramtypes.Subspace, ak authkeeper.AccountKeeper, bk types.BankKeeper, sk types.StakingKeeper, dk types.CommunityPoolKeeper, ek types.EpochKeeper, lk types.LockupKeeper, gk types.GammKeeper, ik types.IncentivesKeeper, lms types.LockupMsgServer, clk types.ConcentratedKeeper, pmk types.PoolManagerKeeper, vspk types.ValSetPreferenceKeeper) *Keeper {
// set KeyTable if it has not already been set
if !paramSpace.HasKeyTable() {
paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
Expand All @@ -52,6 +54,8 @@ func NewKeeper(storeKey sdk.StoreKey, paramSpace paramtypes.Subspace, ak authkee
gk: gk,
ik: ik,
clk: clk,
pmk: pmk,
vspk: vspk,

lms: lms,
}
Expand Down
26 changes: 12 additions & 14 deletions x/superfluid/keeper/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const (
//
// Errors if the lock is not found, if the lock is not a balancer pool lock, or if the lock is not owned by the sender.
func (k Keeper) RouteLockedBalancerToConcentratedMigration(ctx sdk.Context, sender sdk.AccAddress, providedLockId int64, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins) (positionData cltypes.CreateFullRangePositionData, migratedPoolIDs types.MigrationPoolIDs, concentratedLockId uint64, err error) {
synthLockBeforeMigration, migrationType, err := k.routeMigration(ctx, sender, providedLockId, sharesToMigrate)
synthLockBeforeMigration, migrationType, err := k.getMigrationType(ctx, sender, providedLockId)
if err != nil {
return cltypes.CreateFullRangePositionData{}, types.MigrationPoolIDs{}, 0, err
}
Expand Down Expand Up @@ -97,17 +97,15 @@ func (k Keeper) migrateSuperfluidBondedBalancerToConcentrated(ctx sdk.Context,

// Superfluid undelegate the portion of shares the user is migrating from the superfluid delegated position.
// If all shares are being migrated, this deletes the connection between the gamm lock and the intermediate account, deletes the synthetic lock, and burns the synthetic osmo.
intermediateAccount := types.SuperfluidIntermediaryAccount{}

intermediateAccount, err = k.SuperfluidUndelegateToConcentratedPosition(ctx, sender.String(), originalLockId)
intermediateAccount, err := k.SuperfluidUndelegateToConcentratedPosition(ctx, sender.String(), originalLockId)
mattverse marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return cltypes.CreateFullRangePositionData{}, 0, types.MigrationPoolIDs{}, err
}

// Force unlock, validate the provided sharesToMigrate, and exit the balancer pool.
// This will return the coins that will be used to create the concentrated liquidity position.
// It also returns the lock object that contains the remaining shares that were not used in this migration.
exitCoins, err := k.validateSharesToMigrateUnlockAndExitBalancerPool(ctx, sender, migratedPoolIDs.LeavingID, preMigrationLock, sharesToMigrate, tokenOutMins)
exitCoins, err := k.forceUnlockAndExitBalancerPool(ctx, sender, migratedPoolIDs.LeavingID, preMigrationLock, sharesToMigrate, tokenOutMins, true)
if err != nil {
return cltypes.CreateFullRangePositionData{}, 0, types.MigrationPoolIDs{}, err
}
Expand Down Expand Up @@ -153,7 +151,7 @@ func (k Keeper) migrateSuperfluidUnbondingBalancerToConcentrated(ctx sdk.Context
// Force unlock, validate the provided sharesToMigrate, and exit the balancer pool.
// This will return the coins that will be used to create the concentrated liquidity position.
// It also returns the lock object that contains the remaining shares that were not used in this migration.
exitCoins, err := k.validateSharesToMigrateUnlockAndExitBalancerPool(ctx, sender, migratedPoolIDs.LeavingID, preMigrationLock, sharesToMigrate, tokenOutMins)
exitCoins, err := k.forceUnlockAndExitBalancerPool(ctx, sender, migratedPoolIDs.LeavingID, preMigrationLock, sharesToMigrate, tokenOutMins, true)
if err != nil {
return cltypes.CreateFullRangePositionData{}, 0, types.MigrationPoolIDs{}, err
}
Expand Down Expand Up @@ -201,7 +199,7 @@ func (k Keeper) migrateNonSuperfluidLockBalancerToConcentrated(ctx sdk.Context,
// Force unlock, validate the provided sharesToMigrate, and exit the balancer pool.
// This will return the coins that will be used to create the concentrated liquidity position.
// It also returns the lock object that contains the remaining shares that were not used in this migration.
exitCoins, err := k.validateSharesToMigrateUnlockAndExitBalancerPool(ctx, sender, migratedPoolIDs.LeavingID, preMigrationLock, sharesToMigrate, tokenOutMins)
exitCoins, err := k.forceUnlockAndExitBalancerPool(ctx, sender, migratedPoolIDs.LeavingID, preMigrationLock, sharesToMigrate, tokenOutMins, true)
if err != nil {
return cltypes.CreateFullRangePositionData{}, 0, types.MigrationPoolIDs{}, err
}
Expand All @@ -217,9 +215,9 @@ func (k Keeper) migrateNonSuperfluidLockBalancerToConcentrated(ctx sdk.Context,
return positionData, concentratedLockId, migratedPoolIDs, nil
}

// routeMigration determines the status of the provided lock which is used to determine the method for migration.
// getMigrationType determines the status of the provided lock which is used to determine the method for migration.
// It also returns the underlying synthetic locks of the provided lock, if any exist.
func (k Keeper) routeMigration(ctx sdk.Context, sender sdk.AccAddress, providedLockId int64, sharesToMigrate sdk.Coin) (synthLockBeforeMigration lockuptypes.SyntheticLock, migrationType MigrationType, err error) {
func (k Keeper) getMigrationType(ctx sdk.Context, sender sdk.AccAddress, providedLockId int64) (synthLockBeforeMigration lockuptypes.SyntheticLock, migrationType MigrationType, err error) {
Copy link
Member

@ValarDragon ValarDragon Aug 10, 2023

Choose a reason for hiding this comment

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

nice unused arg elimination. We should have a linter warn for unused args (cc @p0mvn )

Copy link
Member

Choose a reason for hiding this comment

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

@pysel just added it here: #6018

// As a hack around to get frontend working, we decided to allow negative values for the provided lock ID to indicate that the user wants to migrate shares that are not locked.
if providedLockId <= 0 {
return lockuptypes.SyntheticLock{}, Unlocked, nil
Expand Down Expand Up @@ -296,15 +294,15 @@ func (k Keeper) validateMigration(ctx sdk.Context, sender sdk.AccAddress, lockId
}, preMigrationLock, remainingLockTime, nil
}

// validateSharesToMigrateUnlockAndExitBalancerPool validates the unlocking and exiting of gamm LP tokens from the Balancer pool. It performs the following steps:
// forceUnlockAndExitBalancerPool validates the unlocking and exiting of gamm LP tokens from the Balancer pool. It performs the following steps:
//
// 1. Completes the unlocking process / deletes synthetic locks for the provided lock.
// 2. If shares to migrate are not specified, all shares in the lock are migrated.
// 3. Ensures that the number of shares to migrate is less than or equal to the number of shares in the lock.
// 4. Exits the position in the Balancer pool.
// 5. Ensures that exactly two coins are returned.
// 6. Any remaining shares that were not migrated are re-locked as a new lock for the remaining time on the lock.
func (k Keeper) validateSharesToMigrateUnlockAndExitBalancerPool(ctx sdk.Context, sender sdk.AccAddress, poolIdLeaving uint64, lock *lockuptypes.PeriodLock, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins) (exitCoins sdk.Coins, err error) {
func (k Keeper) forceUnlockAndExitBalancerPool(ctx sdk.Context, sender sdk.AccAddress, poolIdLeaving uint64, lock *lockuptypes.PeriodLock, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins, exitCoinsLengthIsTwo bool) (exitCoins sdk.Coins, err error) {
czarcas7ic marked this conversation as resolved.
Show resolved Hide resolved
// validateMigration ensures that the preMigrationLock contains coins of length 1.
gammSharesInLock := lock.Coins[0]

Expand All @@ -323,7 +321,7 @@ func (k Keeper) validateSharesToMigrateUnlockAndExitBalancerPool(ctx sdk.Context
return sdk.Coins{}, types.MigratePartialSharesError{SharesToMigrate: sharesToMigrate.Amount.String(), SharesInLock: gammSharesInLock.Amount.String()}
}

// Force migrate, which breaks and deletes associated synthetic locks.
// Force migrate, which breaks and deletes associated synthetic locks (if exists).
err = k.lk.ForceUnlock(ctx, *lock)
if err != nil {
return sdk.Coins{}, err
Expand All @@ -335,8 +333,8 @@ func (k Keeper) validateSharesToMigrateUnlockAndExitBalancerPool(ctx sdk.Context
return sdk.Coins{}, err
}

// Defense in depth, ensuring we are returning exactly two coins.
if len(exitCoins) != 2 {
czarcas7ic marked this conversation as resolved.
Show resolved Hide resolved
// if exit coins length should be two, check exitCoins length
if exitCoinsLengthIsTwo && len(exitCoins) != 2 {
return sdk.Coins{}, types.TwoTokenBalancerPoolError{NumberOfTokens: len(exitCoins)}
}

Expand Down
Loading