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

Average delegation unbonding on multiple requests #492

Closed
wants to merge 1 commit into from

Conversation

abarmat
Copy link
Contributor

@abarmat abarmat commented Aug 10, 2021

Summary

When a delegator undelegates some tokens a delegationUnbondingPeriod is used to calculate the epoch when the tokens will be unlocked. On each new undelegation the period is reset to the unbonding period even if there are tokens waiting to be unlocked. This PR change this behaviour to use a weighted average of time and tokens like on the indexer thawing period.

Current Behavior

It currently works by resetting the unlock epoch on each undelegation.

Example:

  • Epoch 1: Undelegation for 100 GRT, unlock epoch is set to 29
  • Epoch 2: 27 epochs to go for unlocking the tokens
  • Epoch 3: 26 epochs to go for unlocking the tokens
  • Epoch 4: Undelegation for 50 GRT, unlock epoch is set to 32 <- the period is reset for the 150 GRT total tokens

Solution

Use a weighted average formula that consider the time some tokens have already been locked, weighted by the old tokens and the new tokens being undelegated. The formula will round up any fractional epoch value as there is no such thing as half an epoch.

Copy link
Contributor

@davekaj davekaj left a comment

Choose a reason for hiding this comment

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

Looks good, I approved, but I still have a few small questions

// Calculate weighted average multiplying epochs by 10 to add extra precision
// and be able to round the final number up
lockingPeriod = MathUtils.weightedAverage(
MathUtils.diffOrZero(_del.tokensLockedUntil, currentEpoch).mul(10), // Remaining thawing period
Copy link
Contributor

Choose a reason for hiding this comment

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

One thing I am thinking is to make the value 10 as a variable, like uint256 extraPrecision = 10

It is something an auditor mentioned once before, and I liked it, it makes the code more readable.

I feel it is not worth it to make it a global variable. It is not important enough. Maybe just a local function variable. Wdyt?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll do it

Comment on lines +96 to +100
export function weightedAverage(
valueA: BigNumber,
valueB: BigNumber,
weightA: BigNumber,
weightB: BigNumber,
Copy link
Contributor

Choose a reason for hiding this comment

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

It might help to make this function exactly the same params as the solidity function:

    function weightedAverage(
        uint256 valueA,
        uint256 weightA,
        uint256 valueB,
        uint256 weightB
    ) 

Could prevent future bugs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, I'll reorder the input values in the JS function

@@ -446,6 +464,7 @@ describe('Staking::Delegation', () => {
})

it('should undelegate properly when multiple delegations', async function () {
await staking.setDelegationUnbondingPeriod(28)
Copy link
Contributor

Choose a reason for hiding this comment

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

Was this missing from before?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Before it was using a short unbonding period for the tests I needed something longer like on mainnet to test the averaging properly.

@pcarranzav
Copy link
Member

This PR has become quite outdated and would need a big refactor to get merged. I'll close it and we can use it as a reference for a new PR if the corresponding proposal is reactivated.

@pcarranzav pcarranzav closed this Jan 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants