Open sherlock-admin opened 1 year ago
Escalate for 50 USDC Real dups here are #21, #80, #153, #218, which are about uninitialized market allowing unlimited mint as no real transfer is done due to the missing contract code check. Others are dups among themselves, dealing with infinite loop of feeding the contract with Illuminate PTs.
Escalate for 50 USDC Real dups here are #21, #80, #153, #218, which are about uninitialized market allowing unlimited mint as no real transfer is done due to the missing contract code check. Others are dups among themselves, dealing with infinite loop of feeding the contract with Illuminate PTs.
You've created a valid escalation for 50 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
Unlimited mint of Illuminate PTs is possible whenever any market is uninitialized and unpaused
Summary
If some market isn't defined, but not paused, which is true by default, an unlimited mint of Illuminate PTs is possible as
Safe.transferFrom(address(0), ...)
will be successful due to zero address check isn't performed for the token used, while low-level call to zero address is a success.Vulnerability Detail
Lender's mint do not check that principal obtained from
marketPlace
is a viable token. It can be zero address if(u, m, p)
isn't yet defined for a particularp
. In the same timeunpaused(u, m, p)
is true by default corresponding to the uninitialized state.This way once the Lender contract enters the state where
marketPlace
is defined, but some market for some particularp
isn't yet (this is what setPrincipal() is for, i.e. it's a valid use case), and it is not paused (which is by default, as pausing is a manual pause() call), Lender's mint() can be used to issue unlimited number of Illuminate PTs to the attacker.Bob the attacker can setup a script to track such situations for a new Lender contracts. I.e. he can track setMarketPlace() calls and if there is a principal token
IMarketPlace(marketPlace).token(u, m, 0)
created, but some market forp > 0
fromPrincipals
is undefined, but isn't paused, Bob runs Lender's mint and obtains any number ofIMarketPlace(marketPlace).token(u, m, 0)
for free.Impact
An attacker can obtain unlimited Illuminate PTs, subsequently stealing all the funds of any other users with Redeeder's Illuminate redeem(). Such overmint can be unnoticed as it doesn't interfere with any other operations in the system.
The situation described can be a part of normal system setup workflow, unless being specifically handled. The impact itself is full insolvency for a given
(u, m)
. This way setting the severity to be high.Code Snippet
If mint() be called with
p
such thatpaused[u][m][p] == false
and Marketplace'smarkets[u][m][p] == 0
, i.e. both are uninitialized yet, it unlimitedly mints Illuminate PTs for free:https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L264-L288
principalToken(u, m)
is the Illuminate PT for the(u, m)
pair:https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L1047-L1053
IMarketPlace(marketPlace).token(u, m, p)
returnsmarkets[u][m][p]
:https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Marketplace.sol#L601-L611
markets[u][m][p]
might be set or not set by createMarket() and setPrincipal(), there is no control for setup to be full in either of the functions:https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Marketplace.sol#L120-L243
Bob can track setMarketPlace() calls:
https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L249-L262
Observing that
marketPlace
andIMarketPlace(marketPlace).token(u, m, 0)
are set, Bob can call mint() to obtain Illuminate PTs for a given(u, m)
.To check that current Safe does call zero address successfully please see the POC (it's basically tenderly start script with
IERC20
andSafe
copied over):https://sandbox.tenderly.co/dmitriia/safe-transfer-zero
Tool used
Manual Review
Recommendation
As Lender's mint() might be not the only instance where the absence of token existence check opens up this attack surface, consider requiring token address to have code in all Safe operations.
Also, controlling that PT address obtained isn't zero is advised in all the instances where is it used, for example:
https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Lender.sol#L264-L288