-
Notifications
You must be signed in to change notification settings - Fork 607
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
Pool Cleanup #652
Pool Cleanup #652
Conversation
Co-authored-by: Sunny Aggarwal <[email protected]>
Is the idea of setting a destruction time that I can make a pool get deleted in the current block (e.g. at upgrade), and schedule a deletion in the future? Shouldn't we make it so that the pool deletion also deletes the pool from state, or is it a goal / low cost to keep the literal pool in state as long as its marked inactive for integrators? |
x/gamm/keeper/pool.go
Outdated
if !pool.GetTotalShares().IsZero() { | ||
panic("pool total share should be zero after cleanup") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can zero share be assured everytime(division factor etc.)?
My only concern is that it might not: considering the fact that I remember that somewhere in the code what we did was iterate through coins and send a part of it every iteration, and at the last iteration, we would send the all the remainings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great point, I originally thought the total shares are only added/subtracted, not divided; I will check if there are any case of division.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this fixed? / checked?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because shares are just a sdk.Coin, it could be IBC'd out or sent to module logics, and stay under the module account. I am pretty sure if we count all the address held shares and module held shares, it would sum up to GetTotalShares(). Let me add the logic for module accounts to(or, is it already iterated by GetAllBalances?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you investigate if module accounts are iterated over? I think we should definitely exclude certain module accounts, e.g. IBC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The iteration do include the module accounts. I will exclude the module account held LP tokens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, annoyingly, there is no way to distinguish module address and normal address by only using the address itself. We could read all the module address and compare to them each time iterating over the list of address, but at this stage it feels little adhoc. Let me think about some alternatives a bit.
Similar but different to @ValarDragon 's comment, I'm curious when this |
|
I intended pool destruction in order to make it able to resurrected in the future, but I think we don't need to store the actual time here. However, I agree that it does not really make sense to just pause the pool in this use case, as we completely destruct the pool and refund the whole assets. I will change it to state removal.
It is designed to ran on the chain upgrade time, so we don't have a lot of computation time restriction.
|
…mosis into mconcat/502-pool-cleanup
Codecov Report
@@ Coverage Diff @@
## main #652 +/- ##
==========================================
+ Coverage 18.69% 18.73% +0.04%
==========================================
Files 171 171
Lines 23816 23901 +85
==========================================
+ Hits 4452 4478 +26
- Misses 18601 18649 +48
- Partials 763 774 +11
Continue to review full report at Codecov.
|
R4R |
Notes from call earlier today/yesterday |
poolAssets := pool.GetAllPoolAssets() | ||
|
||
// first iterate through the share holders and burn them | ||
k.bankKeeper.IterateAllBalances(ctx, func(addr sdk.AccAddress, coin sdk.Coin) (stop bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets file an issue to revisit performance of this. Either we:
- change to do one iteration for all pools
- wait for perf: x/bank create reverse prefix for denom<->address cosmos/cosmos-sdk#9611 to get merged into a release before we actually do the upgrade
- iterate over addresses directly, and just get the balance of the relevant coin (rather than iterate over every addr,coin pair)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait aren't we going to be iterating over IBC's module accounts like this? If so, we will be making IBC'd tokens never redeemable. Do we need to care about this, cc @sunnya97 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the original issue I think the IBC'd LP tokens are never redeemable for now(also there is no use case of IBCing out LP tokens yet). I could apply the first and the third suggestion now.
x/gamm/keeper/pool.go
Outdated
return | ||
} | ||
|
||
shareAmount := coin.Amount |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets alias coin to userPoolShare
here. I think it makes a lot of subsequent lines easier to read
x/gamm/keeper/pool.go
Outdated
|
||
// Refund assets | ||
for _, asset := range poolAssets { | ||
assetAmount := asset.Token.Amount.Mul(shareAmount).Quo(totalShares) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assetAmount := asset.Token.Amount.Mul(shareAmount).Quo(totalShares) | |
// lpShareEquivalentTokens = (amount in pool) * (your shares) / (total shares) | |
lpShareEquivalentTokens := asset.Token.Amount.Mul(shareAmount).Quo(totalShares) |
This still needs to be done right? (I'm still seeing the destruction time logic) |
x/lockup/keeper/lock.go
Outdated
func (k Keeper) GetLocksDenom(ctx sdk.Context, denom string) []types.PeriodLock { | ||
unlockings := k.getLocksFromIterator(ctx, k.LockIteratorDenom(ctx, true, denom)) | ||
notUnlockings := k.getLocksFromIterator(ctx, k.LockIteratorDenom(ctx, false, denom)) | ||
return combineLocks(notUnlockings, unlockings) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pretty surprised we don't already have a function for this lying around, pretty sure we use it in distribution
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm... True... Did we / can we use GetLocksLongerThanDurationDenom
with duration set to 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That worked!
x/lockup/keeper/lock.go
Outdated
// remove lock from store object | ||
store := ctx.KVStore(k.storeKey) | ||
store.Delete(lockStoreKey(lock.ID)) | ||
|
||
var keyprefix []byte | ||
if lock.IsUnlocking() { | ||
keyprefix = types.KeyPrefixUnlocking | ||
} else { | ||
keyprefix = types.KeyPrefixNotUnlocking | ||
} | ||
|
||
// delete lock refs from the unlocking queue | ||
err = k.deleteLockRefs(ctx, keyprefix, lock) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// remove from accumulation store | ||
for _, coin := range lock.Coins { | ||
k.accumulationStore(ctx, coin.Denom).Decrease(accumulationKey(lock.Duration), coin.Amount) | ||
} | ||
|
||
k.hooks.OnTokenUnlocked(ctx, owner, lock.ID, lock.Coins, lock.Duration, lock.EndTime) | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we reuse logic from the existing methods for a lock going from NotUnlocking -> Unlocking, and Unlocking -> finish unlocking?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do so!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Problem is that the existing method checks whether the time has been passed specified on the lock duration, and ForceUnlock need to ignore them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed by separating duration validation and actual unlocking logic
Few modification needed:
|
We don't need to optimize performance for this PR, can just write an issue. (Performance gets ~basically solved if we just wait lol) |
Co-authored-by: Dev Ojha <[email protected]>
|
moduleAccounts := make(map[string]string) | ||
for _, module := range excludedModules { | ||
moduleAccounts[string(authtypes.NewModuleAddress(module))] = module | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, looks good to merge to me! Thanks for fixing everything and addressing comments
Closes: #502
Description
For contributor use:
docs/
) or specification (x/<module>/spec/
)Unreleased
section inCHANGELOG.md
Files changed
in the Github PR explorer