-
Notifications
You must be signed in to change notification settings - Fork 1
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
0x73696d616f - Admin new issuance or user calling Vault::redeemExpiredLv()
after Psm::redeemWithCt()
will lead to stuck funds when trying to withdraw
#156
Comments
related to #44, the function that's problematic here is |
Vault::redeemExpiredLv()
after Psm::redeemWithCt()
will lead to stuck funds when trying to withdrawVault::redeemExpiredLv()
after Psm::redeemWithCt()
will lead to stuck funds when trying to withdraw
escalate This issue is high severity because it has no external dependencies, it will happen whenver new DS tokens are issued. |
You've created a valid escalation! To remove the escalation from consideration: Delete your comment. You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final. |
You've deleted an escalation for this issue. |
The problem is not in |
The reason why this issue is Medium is because it has an external condition. This issue can only happen under certain conditions mentioned in the issue.
|
@cvetanovv that is not an external condition, it's within the protocol (same contract to be more precise).
So 2 means it always happens and 1 means anyone may trigger this. Which means this has internal conditions but they are not extensive, can be easily triggered by 1 and will always be triggered by 2. |
There may be several mitigations, it's easier to verify the pr. |
For this issue, there are not two mitigations. Reducing the Additionally, mitigating in a different area does not mean that the issues are separate; instead, we should focus on the root cause. |
I would have to check the pr to confirm.
Sherlock duplication rules require the root cause and attack path to be the same, which they are not. There are many different ways to make the accounting wrong. Even then, there are several assets in the protocol, ra, pa and ct. This issue is related to ct accounting specifically, not ra or pa, as the ct attributed to the vault would not be used to redeem via |
Issues related to accounting for the exchange rate as
No. The ct attributed to the vault should be used to redeem ra. The ct attributed to the vault belongs to the lv holders (who contributed to the Uniswap V2 pool). They sent ra to the vault, and some of that ra was exchanged for (ct + ds). The generated ct was provided to the Uniswap V2 pool along with the remaining ra, and the generated ds were sent to the FlashSwapRouter. Therefore, when issuing new ds, the ct liquidated from the Uniswap V2 pool and the ds from the FlashSwapRouter should be reexchanged for ra. If they are not reexchanged, it will result in a loss of funds for the lv holders. Thus, skipping |
But that is always the same fix, taking the exchange rate into account.
Lv holders just hold lv, the lps are held by the vault. Users do not hold all ct at this point, some of it is in the univ2 pool, a part of it owned by the vault and the corresponding lps.
Exactly, the vault holds the lps, whose ct is in the uni v2 pool.
Again, I am not discussing the mitigation, but the bug is in the ct amount held by the vault. Look at the order of events PsmLibrary.onNewIssuance(state, ct, ds, ammPair, idx, prevIdx, repurchaseFeePrecentage);
getRouterCore().onNewIssuance(id, idx, ds, ammPair, 0, ra, ct);
VaultLibrary.onNewIssuance(state, prevIdx, getRouterCore(), getAmmRouter()); Firstly, Secondly, Lastly, as there was enough reserve, no ct is left to redeem with If we look into accrued = (amount * (available * 1e18) / totalCtIssued) / 1e18;
|
The protocol team fixed this issue in the following PRs/commits: |
About the severity, @0xsimao could you elaborate on the impact:
What would be the approximate loss here? About the duplication, #166, #126 and #155 have different root causes, and this report shouldn't be a duplicate of any of these. Please correct me if it's wrong. |
Whatever the |
Thank you for this clarification. Since the loss can indeed be high and the constraints in the report are not extensive, planning to accept the escalation and upgrade the severity to high. |
In the
and in the
So, no stuck amount. |
The stuck amount is significant because all the ct the vault held will not be able to redeem the ra and pa tokens. It is stuck because the checkpoint is taken before the vault burns its ct. So the decrease mentioned here will never fully happen because the vault has burned its ct. So ra and pa will be stuck. The checkpoint is taken before, on Then, it calls As such, the checkpointed total ct will have a component that was burned and will never be redeemed. |
@0xsimao, you are correct that To summarize, both As a result, we cannot conclude that Regarding Therefore, the severity of this issue should be considered medium. |
Both ra and pa accrued will never decrease, as there is not enough ct to redeem them. |
My decision remains unchanged, even though there are some constraints to trigger the issue. They're not extensive, and the issue could easily happen, leading to completely stuck tokens. Hence, the decision remains: accept the escalation and upgrade severity to high. |
Result: |
Escalations have been resolved successfully! Escalation status:
|
0x73696d616f
High
Admin new issuance or user calling
Vault::redeemExpiredLv()
afterPsm::redeemWithCt()
will lead to stuck funds when trying to withdrawSummary
VaultLib::_liquidatedLp() calls PsmLib::lvRedeemRaWithCtDs(), which redeems
ra
withct
andds
. However, if PsmLib::_separateLiquidity() has already been called, this will lead to an incorrect tracking of funds asPsmLib::_separateLiquidity()
checkpointed the total supply ofct
, but theVault
will redeem some of it usingPsmLib::lvRedeemRaWithCtDs()
, leading to somepa
that will never be withdrawn and the vault withdraws too manyRa
, which means users will not be able to redeem theirct
forra
andpa
asra
has been withdrawn already and it reverts.Root Cause
In
VaultLib.sol:377
, it callsPsmLib::lvRedeemRaWithCtDs()
even ifPsmLib::_separateLiquidity()
has already been called. It should skip it in this case.Internal pre-conditions
PsmLib::_separateLiquidity()
needs to be called beforeVaultLib::_liquidatedLp()
, which may be done on a new issuance when the admin calls ModuleCore::issueNewDs() or by users callingPsm::redeemWithCT()
beforeVault::redeemExpiredLv()
.External pre-conditions
None.
Attack Path
ModuleCore::issueNewDs()
.Or users call
Psm::redeemWithCT()
beforeVault::redeemExpiredLv()
.Impact
As the
Vault
withdrawsRa
after the checkpoint and burns the correspondingCt
tokens, it will withdraw too manyra
and not withdraw thepa
it was entitled to.PoC
ModuleCore::issueNewDs()
callsPsmLib::onNewIssuance()
beforeVaultLib::onNewIssuance()
always triggering this bug.PsmLib::_separateLiquidity()
checkpointsra
andpa
based onct
supply:VaultLib::_liquidatedLp()
redeemsra
withct
andds
when it should have skipped it has liquidity has already been checkpointed inPsmLib::_separateLiquidity()
.Mitigation
If the liquidity has been separated, skip redeeming
ra
forct
andds
.The text was updated successfully, but these errors were encountered: