-
Notifications
You must be signed in to change notification settings - Fork 144
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
Conversation
b8828a3
to
2b6edfd
Compare
2b6edfd
to
dedfa31
Compare
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.
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 |
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.
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?
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.
I'll do it
export function weightedAverage( | ||
valueA: BigNumber, | ||
valueB: BigNumber, | ||
weightA: BigNumber, | ||
weightB: BigNumber, |
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.
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
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.
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) |
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.
Was this missing from before?
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.
Before it was using a short unbonding period for the tests I needed something longer like on mainnet to test the averaging properly.
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. |
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:
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.