Shortfall contract is used to clear off any pool bad debt via auction. If the debt reached its mimimum value, anybody can start off the auction and place the bid.
Attacker can bid with token(e.g. USDC, USDT) that have a contract level admin controlled address blocklist. Attacker first call the Shortfall.sol#placeBid() and just after that gets into blocklist, which cause any transfers to to and from get failed, this prevent other user placing the bid higher than attacker. And once the auction is closed via Shortfall.sol#closeAuction(), the attacker would able to claim the highest amount of reserve funds.
Proof of Concept
Consider poolBadDebt accrued to the minimumPoolBadDebt and auction has started.
Attacker placeBid() with max bidBps(say 10,000).
Got into the blocklist with some malicious activity, makes here transfer to fail for currentBidder.
Finally, calling the closeAuction() in order to claim max reserve amount, after 10 blocks time passed.
Tools Used
Manual audit
Recommended Mitigation Steps
Instead of transferring fund back to the bidder, create a new mappings that keeps record of their balance and a function, which allow to claim recorded balance back. More details here
Lines of code
https://github.com/code-423n4/2023-05-venus/blob/8be784ed9752b80e6f1b8b781e2e6251748d0d7e/contracts/Shortfall/Shortfall.sol#L183 https://github.com/code-423n4/2023-05-venus/blob/8be784ed9752b80e6f1b8b781e2e6251748d0d7e/contracts/Shortfall/Shortfall.sol#L190
Vulnerability details
Impact
Shortfall contract is used to clear off any pool bad debt via auction. If the debt reached its mimimum value, anybody can start off the auction and place the bid.
Attacker can bid with token(e.g. USDC, USDT) that have a contract level admin controlled address blocklist. Attacker first call the
Shortfall.sol#placeBid()
and just after that gets into blocklist, which cause any transfers toto
andfrom
get failed, this prevent other user placing the bid higher than attacker. And once the auction is closed via Shortfall.sol#closeAuction(), the attacker would able to claim the highest amount of reserve funds.Proof of Concept
Consider
poolBadDebt
accrued to theminimumPoolBadDebt
and auction has started.placeBid()
with maxbidBps
(say 10,000).closeAuction()
in order to claim max reserve amount, after 10 blocks time passed.Tools Used
Manual audit
Recommended Mitigation Steps
Instead of transferring fund back to the bidder, create a new mappings that keeps record of their balance and a function, which allow to claim recorded balance back. More details here
Assessed type
DoS