Reentrancy in _close()
allows single lender to steal all deposits from other lenders
#498
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
downgraded by judge
Judge downgraded the risk level of this issue
duplicate-160
satisfactory
Finding meets requirement
Lines of code
https://github.com/debtdao/Line-of-Credit/blob/e8aa08b44f6132a5ed901f8daa231700c5afeb3a/contracts/modules/credit/LineOfCredit.sol#L483-L495
Vulnerability details
Impact
Upon calling
close()
, a lender's credit position is deleted AFTER the transfer out of their deposit. Therefore, an ERC777 will allow the lender to callclose()
again and receive the same amount of funds. The lender will be able to reenter the contract as many times as necessary to drain the token balance.Proof of Concept
A lender or borrower can call
close()
which eventually calls_close()
. The purpose is to return the lender's capital back to them and then delete the position. Since the position isn't deleted until after the transfer occurs, a token with a callback hook, such as an ERC777 or non-standard token like AMP will allow the lender to reenter.NOTE: In the current implementation, only tokens with callbacks are susceptible because the transfer of ETH is performed with
transfer()
. Wardens will flag this issue which might result in the DebtDAO team altering the implementation tocall()
. If/when they do, ETH transfers will be susceptible to reentrancy as well.The bottom half of the
_close()
function does not contain any logic that would cause a revert.removePosition()
does not revert if the position does not exist.--count
is contained in an unchecked block, the UINT will underflow successfully.count
will not equaltrue
.Tools Used
Manual review.
Recommended Mitigation Steps
Delete the
credits[id]
position prior to the transfer or add reentrancy guards.The text was updated successfully, but these errors were encountered: