-
Notifications
You must be signed in to change notification settings - Fork 1
Vagner - _unwrap
in MultiInvoker.sol
can revert every time in some cases which will make the users not being able to _liquidate
or _withdraw
with warp
to true
#22
Comments
3 comment(s) were left on this issue during the judging contest. 141345 commented:
n33k commented:
panprog commented:
|
_unwrap
in MultiInvoker.sol
can revert every time in some cases which will make the users not being able to _liquidate
or _withdraw
with warp
to true_unwrap
in MultiInvoker.sol
can revert every time in some cases which will make the users not being able to _liquidate
or _withdraw
with warp
to true
The condition is
But at first place, USDC is wrapped into DSU by batcher. File: perennial-v2\packages\perennial-extensions\contracts\MultiInvoker.sol
271: function _wrap(address receiver, UFixed18 amount) internal {
277: // Wrap the USDC into DSU and return to the receiver
278: batcher.wrap(amount, receiver); So the USDC in batcher is expected to be fully backed. Hence low/info severity is more appropriate. |
Yes that is true, but that is not the issue that I'm talking about here, I'm not saying that there will not be enough funds in the batcher to be paid back. The issue that I've talked here is the fact that DSU protocol can borrow DSU, which will increase the debt of the protocol, as can be seen here |
Sorry I misunderstood the report. The DSU reserve has borrow function result in debt, and the redeem amount will not be enough. Or we can say it is when DSU depeg from USDC. Seems an edge case issue. |
Yep, it is an edge case, that's why in my escalation I specify that should be treated at least as a medium, since the damage exist and can be quite high and as for probability, it depends a lot on how DSU maintain their balance sheets, since the function can be called anytime by the owners, and since it was specify that Perennial team wants to know integration issue that could occur with DSU, it is in their advantage to protect their protocol against this case. |
Result: |
Escalations have been resolved successfully! Escalation status:
|
From WatchPug: Acknowledged |
Vagner
high
_unwrap
inMultiInvoker.sol
can revert every time in some cases which will make the users not being able to_liquidate
or_withdraw
withwarp
to trueSummary
_withdraw
makes some wrong assumptions which could lead to reverts all the time ifDSU
protocol will be in debt.Vulnerability Detail
The function
_withdraw
is called in_liquidate
,_vaultUpdate
and_update
, and if thewrap
is set to true, which will be all the time in the case of_liquidate
, it will try to call_unwrap
https://github.com/sherlock-audit/2023-07-perennial/blob/main/perennial-v2/packages/perennial-extensions/contracts/MultiInvoker.sol#L262After that
_unwrap
will check if the address ofbatcher
is 0, which can be the case if it is not set up in the constructor, or if thebalanceOf
USDC ofbatcher
is less than the amount intended to withdrawhttps://github.com/sherlock-audit/2023-07-perennial/blob/main/perennial-v2/packages/perennial-extensions/contracts/MultiInvoker.sol#L287
and if any of that will be true it will try to call the
redeem
function onreserve
with the intended amounthttps://github.com/sherlock-audit/2023-07-perennial/blob/main/perennial-v2/packages/perennial-extensions/contracts/MultiInvoker.sol#L288
and then transfers the
amount
to thereceiver
https://github.com/sherlock-audit/2023-07-perennial/blob/main/perennial-v2/packages/perennial-extensions/contracts/MultiInvoker.sol#L289
The problem relies in the fact that the protocol assumes that the
amount
that is used inredeem
function will always be equal to theamount
of USDC returned, which is not the case.As can be seen in the code of the
reserve
here theredeemAmount
is a calculation that depends on theredeemPrice
which depends on the debt of the protocolhttps://github.com/emptysetsquad/emptyset/blob/c5d876fbd8ff1fac988898b77ef5461971f9fdd2/protocol/contracts/src/reserve/ReserveComptroller.sol#L125
The whole calculation of
redeemPrice
is done depending of thereserveRatio
of the Protocolhttps://github.com/emptysetsquad/emptyset/blob/c5d876fbd8ff1fac988898b77ef5461971f9fdd2/protocol/contracts/src/reserve/ReserveComptroller.sol#L81-L84
so in the case where DSU will make some bad decisions and it will be in debt the
redeemAmount
calculated will be less than the actual amount inserted intoredeem
function, and thatredeemAmount
will be the one actual transferred to theMultiInvoker.sol
https://github.com/emptysetsquad/emptyset/blob/c5d876fbd8ff1fac988898b77ef5461971f9fdd2/protocol/contracts/src/reserve/ReserveComptroller.sol#L130
So when
_unwrap
will try to transfers the same amount of USDChttps://github.com/sherlock-audit/2023-07-perennial/blob/main/perennial-v2/packages/perennial-extensions/contracts/MultiInvoker.sol#L289
the transaction would revert because the contract would not have enough USDC in the contract, making
_vaultUpdate
,_update
withwarp
to true on_withdraw
reverting all the time and_liquidate
reverting 100% of the time. Since the protocol stated that they want to be aware of any issue that might arise with the integration of DSUI decided to specify this issue which could happen can cause a lot of damage to the users.
Impact
Impact is a high one since it will cause the liquidation process to fail and also withdrawing funds to fail.
Code Snippet
https://github.com/sherlock-audit/2023-07-perennial/blob/main/perennial-v2/packages/perennial-extensions/contracts/MultiInvoker.sol#L285-L289
Tool used
Manual Review
Recommendation
Since the contract doesn't store any USDC, you could transfer the whole balance of the contract every time after you call
redeem
or do balance before and balance after, and transfer the difference. It is important to take special care when you implement other protocols since any failures will also break your protocol.The text was updated successfully, but these errors were encountered: