In VaultRouterBranch
::unstake
There is a check that ensures a LP provider can only unstake if they have no available rewards.
The rewards are accounted in Distributio
, which keeps track of distributing value to the vault (rewards to be claimed by LP providers based on how many shares they have).
But, the vault's value gets updated with every user action. This makes the vault's value to distribute and the LP providers rewards ever-changing.
This constant change in value can make it very difficult to pass the check in unstake
-> which would revert an unstake
.
In unstake
there is this check that ensures that the user does not have any pending/claimable rewards, if they do they cant unstake:
This value (amount of rewards for LP provider) gets updated via this process:
The vault calculates and updates various amounts, but for this case, we are focusing on the vault updating and distributing value to the Distributor
contract. That is the vault the LP provider has shares in. Everytime this function is called, the vault can have new value distributed to it. This function is called during every user action, meaning the vault can receive value and change the rewards amount for a user at every action.
The Distributor
contract distributes
the new value by updating valuePerShare
That value update is used to determine new rewards for LP provider
So, every time recalculateVaultsCreditCapacity
is called for that vault, their can be new pending rewards for LP providers.
IF unstake
fails because of this, the user can go to the FeeDistributionBranch
and claimFees
to try and claim the fee's so that they can unstake.
But FeeDistributionBranch::claimFees
does not call recalculateVaultsCreditCapacity
-> so the reward amount will be at the current state (before updating Distribution
)
The user will have their accounting in Distribution
updated so that their lastValuePerShare
= the contracts current (not most current, becasue the update didnt happen) valuePerShare
-> which will equate to them not having any new rewards.
This would allow the check in unstake
to pass.
BUT, any user action in that vault will update the vaults rewards and subsequetly adding new pending rewards to the user.
Also, when the user goes back to unstake
after claiming their rewards, recalculateVaultsCreditCapacity
is called again and can update the rewards they have pending. Making them fail the check in unstake
again and not allowing them to unstake.
It can be difficult for LP providers to unstake and even if they claim their rewards, by the time they unstake
their vault could have been updated and their unstake
would fail.
Only allowing them to unstake
if no updates to the vault are made.
Manual Review
Becasue the rewards are paid through FeeDistributionBranch
and not VaultBranchRouter
-> if the user has pending rewards after the update which is called at the beginning of unstake
:
The claimable rewards amount can be stored seperately, allowing the user to them claimFee
even after their unstake
has processed. The user wont be able to generate any new rewards, but only able to claim the rewards they have earned (which is what the check in unstake
is allowing / enforcing anyways).
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.