Open sherlock-admin opened 1 year ago
Escalate for 1 USDC I would like to request reevaluation of the duplication grouping. Currently, all issues that mention reentrancy are grouped together and count as 1 issue. As you can see in the list of duplicates, most wardens have submitted 2 issues, one for the affected lending functions and one for the single redeem function that is affected. Grouping them as a single issue would effectively punish those that put in the effort to identify both the affected lending and redeem parts, as well as describing the vulnerability details and impact (which are different), compared to those who only submitted the issue for the lending related code.
Escalate for 1 USDC I would like to request reevaluation of the duplication grouping. Currently, all issues that mention reentrancy are grouped together and count as 1 issue. As you can see in the list of duplicates, most wardens have submitted 2 issues, one for the affected lending functions and one for the single redeem function that is affected. Grouping them as a single issue would effectively punish those that put in the effort to identify both the affected lending and redeem parts, as well as describing the vulnerability details and impact (which are different), compared to those who only submitted the issue for the lending related code.
You've created a valid escalation for 1 USDC!
To remove the escalation from consideration: Delete your comment. To change the amount you've staked on this escalation: Edit your comment (do not create a new comment).
You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.
Escalate for 100 USDC
I just want to add more weight to the issue raised by @Minh-Trng above. They wrote it better than I could so I quote:
I would like to request reevaluation of the duplication grouping. Currently, all issues that mention reentrancy are grouped together and count as 1 issue. As you can see in the list of duplicates, most wardens have submitted 2 issues, one for the affected lending functions and one for the single redeem function that is affected. Grouping them as a single issue would effectively punish those that put in the effort to identify both the affected lending and redeem parts, as well as describing the vulnerability details and impact (which are different), compared to those who only submitted the issue for the lending related code.
Escalate for 100 USDC
I just want to add more weight to the issue raised by @Minh-Trng above. They wrote it better than I could so I quote:
I would like to request reevaluation of the duplication grouping. Currently, all issues that mention reentrancy are grouped together and count as 1 issue. As you can see in the list of duplicates, most wardens have submitted 2 issues, one for the affected lending functions and one for the single redeem function that is affected. Grouping them as a single issue would effectively punish those that put in the effort to identify both the affected lending and redeem parts, as well as describing the vulnerability details and impact (which are different), compared to those who only submitted the issue for the lending related code.
You've created a valid escalation for 100 USDC!
To remove the escalation from consideration: Delete your comment. To change the amount you've staked on this escalation: Edit your comment (do not create a new comment).
You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.
Escalation accepted
Escalation accepted
This issue's escalations have been accepted!
Contestants' payouts and scores will be updated according to the changes made on this issue.
hyh
high
Yield, Swivel, Element, APWine and Sense lend() are subject to reentracy resulting in Illuminate PT over-mint
Summary
Lender's lend() versions for Yield, Swivel, Element, APWine and Sense use balance difference for the net result calculation, i.e. how much Illuminate PTs to mint for the caller, and call user-provided contract to perform the swapping. The functions aren't protected from reentrancy.
This opens up an attack surface when the functions are being called repetitively, and, while the first call result is accounted once, nested calls, dealing with the same type of PTs, are accounted multiple times, leading to severe Illuminate PT over-mint.
Vulnerability Detail
Taking Yield version as an example, Bob the attacker can provide custom-made contract
y
instead of Yield Space Pool.y
do call the real pool, but before that it calls the same lend() with the same parameters (apart from amount), soy
got called again.Let's say it happens 2 extra times. Let's say the first call is done with
10 DAI
, the second with100 DAI
, the third with10^6 DAI
, i.e. Bob needs to provide10^6 + 10^2 + 10^1 DAI
. Let's say it is done right before maturity and there is no discounting remaining, i.e.1 DAI = 1 PT
.The result of the first yield() call will be accounted once, as designed. The result of the second, nested, call, will be accounted twice as it mints to the user according to the yield() call performed and increases the Yield PT balance, which is counted in the first lend(). The result of the third call will be accounted in all lend() functions.
This way first lend() will mint
1 * 10^6 + 1 * 10^2 + 1 * 10^1
as it will be the total Yield PT balance difference from the three yield() calls it performed directly and nested, i.e. the balance will be counted before the swapping started, the second time it will be counted when all three swaps be completed. The second lend() will mint1 * 10^6 + 1 * 10^2
as it be finished before first yield() do its swap. The third lend() will mint1 * 10^6
, having no further calls nested.Bob will get
3 * 10^6 + 2 * 10^2 + 1 * 10^1
Illuminate PT minted for the10^6 + 10^2 + 10^1
DAI provided.Impact
The impact is massive Illuminate PTs over-mint that result in attacker being able to steal the funds of all other users by redeeming first the whole underlying amount due to the type of Illuminate PTs he obtained.
As there are no low probability prerequisites, setting the severity to be high.
Code Snippet
Similar in all: Bob creates a wrapper that calls the same version of lend() with the same parameters, then calls the correct pool. In each version of lend() there are a user-provided contract that is called to perform the operation, allowing for reentracy.
Yield lend() calls yield() with user-provided contract
y
, that is called in-between balance recording:https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L290-L347
https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L919-L957
Similarly, Swivel lend() calls yield() with user-supplied Yield Space Pool
y
via swivelLendPremium():https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L349-L449
https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L959-L979
This way both Yield and Swivel call yield() with user-supplied pool
y
and mint the difference obtained with they
call to a user.Element lend calls elementSwap() with user-supplied pool
e
and mints the balance difference:https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L451-L511
elementSwap() similarly calls user-supplied
e
to perform the swapping and mints the balance difference:https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L1000-L1028
APWine lend() in the same manner calls user-supplied pool
x
and mints the balance differencereceived
:https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L562-L621
Sense lend() also directly calls user-supplied AMM
x
and mints the balance difference to a caller:https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L681-L741
Tool used
Manual Review
Recommendation
Consider adding reentracy guard modifier to Yield, Swivel, Element, APWine and Sense lend() functions of the Lender.
Notice that although Pendle, Tempus and Notional versions of lend() look to be resilient to the attack as they use either internal address (Pendle and Notional) or verify the supplied address (Tempus, https://github.com/tempus-finance/fixed-income-protocol/blob/master/contracts/TempusController.sol#L63) the same reentracy guard modifier can be used there as well as a general approach as these functions still mint the recorded balance difference to a user and there might exist yet unnoticed possibility to game it.
In all these cases either direct removal of the attack surface or precautious control for it do justify the reentracy guard gas cost.