Open c4-bot-2 opened 5 months ago
GalloDaSballo marked the issue as duplicate of #212
GalloDaSballo marked the issue as sufficient quality report
trust1995 marked the issue as satisfactory
trust1995 marked the issue as selected for report
This then leads to some tokens unusable (like USDT for example) and this topic was already discussed severely during hats competition where I can send links to findings, so should be scraped in my opinion. Also sufficient checks are already done in _callOptionalReturn directly.
For transparency and per conversation with the sponsors, see here for the Wise Lending team's mitigation.
Additionally: WiseLending is not meant to be used with corrupted tokens that have unsupported transfer/transferFrom implementations.
Lines of code
https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/TransferHub/CallOptionalReturn.sol#L21 https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/TransferHub/CallOptionalReturn.sol#L26-L29 https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/TransferHub/CallOptionalReturn.sol#L35-L37 https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/TransferHub/TransferHelper.sol#L42
Vulnerability details
Impact
Currently, the
Wise Lending
protocol supports several ERC-20 tokens and will also support more tokens in the future:On some ERC-20 tokens, the
transferFrom()
will returnfalse
on failure instead of reverting a transaction. I noticed that theTransferHelper::_safeTransferFrom()
, which is used throughout the protocol, is vulnerable to detecting the token transfer failure if thetransferFrom()
returnsfalse
due to the unchecked return value bug.The following lists the functions directly invoking the vulnerable
_safeTransferFrom()
:Due to the unchecked return value bug, users or attackers can exploit these protocol's functions without supplying a token (please refer to the
Proof of Concept
section for more details).Proof of Concept
The
Wise Lending
protocol implements theTransferHub::_callOptionalReturn()
as a helper function for executing low-level calls. In case thetransferFrom()
returnsfalse
on failure, the_callOptionalReturn()
will receive the returned parameters:success
== true andreturndata
!= bytes(0).Then, the
_callOptionalReturn()
will decode the receivedreturndata
for the success status. If thetransferFrom()
returnsfalse
, theresults
will becomefalse
.With the
results
==false
, finally, the_callOptionalReturn()
will returnfalse
to its function caller.On the
TransferHelper::_safeTransferFrom()
, I noticed that the function does not evaluate the return value (i.e., unchecked return value bug) of the_callOptionalReturn()
. Subsequently, the_safeTransferFrom()
cannot detect the token transfer failure if thetransferFrom()
returnsfalse
.@1 -- On some tokens, the transferFrom() will return false instead of reverting a transaction
: https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/TransferHub/CallOptionalReturn.sol#L21@2 -- If the transferFrom() returns false, the results == false
: https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/TransferHub/CallOptionalReturn.sol#L26-L29@3 -- If the results == false, the _callOptionalReturn() will return false
: https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/TransferHub/CallOptionalReturn.sol#L35-L37@4 -- The _safeTransferFrom() cannot detect the token transfer failure if the transferFrom() returns false instead of reverting a transaction due to the unchecked return value bug
: https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/TransferHub/TransferHelper.sol#L42Note: Please refer to the
Impact
section for a complete list of the functions directly invoking the vulnerable_safeTransferFrom()
.The following briefly analyzes 2 of the 17 functions that would affect the exploitation as examples.
Due to the unchecked return value bug, the
WiseCore::_coreLiquidation()
cannot be aware of the token transfer failure. Thus, a rogue liquidator can steal collateral from the target liquidable position without supplying any debt token (tokenToPayback
).On the
WiseLending::depositExactAmount()
, a rogue depositor can increase their collateral without spending any token.@5 -- Liquidator can steal collateral (_receiveToken) from the target liquidable position
: https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseCore.sol#L674-L679@6 -- Depositor can increase their collateral without supplying any token
: https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L476-L481Tools Used
Manual Review
Recommended Mitigation Steps
Improve the
_safeTransferFrom()
by checking the return value from the_callOptionalReturn()
and reverting a transaction if it isfalse
.Assessed type
Invalid Validation