Closed code423n4 closed 2 years ago
You can't try catch a call(). On a revert, call() returns a boolean of false which is handled by our code.
Agree with @batu-inal here, if an external contract reverts when .call()
is used -- it will return false instead of reverting the entire transaction. Our code handles this so that the minting will still complete successfully.
Lines of code
https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/mixins/shared/SendValueWithFallbackWithdraw.sol#L34-L50
Vulnerability details
Impact
When a user purchases a NFT via
NFTDropMarketFixedPriceSale.mintFromFixedPriceSale
, funds are distributed via a call toMarketFees._distributeFunds
. During this call, the following users are paid:When paying each of these users,
SendValueWithFallbackWithdraw._sendValueWithFallbackWithdraw
is called which first makes acall
to each user and if that fails, callsFETH.depositFor
.What's important here is that
_sendValueWithFallbackWithdraw
calls
the user. For example:Unfortunately, a user can revert a call made to them by modifying their contract to revert when funds are sent to the contract. This results in the following users below having the opportunity to halt a NFT sale via reverting calls made to their address:
Proof of Concept
The
SendValueWithFallbackWithdraw._sendValueWithFallbackWithdraw
function does not wrap the call in a try statement to catch the call reversion. Because of this, a revert whencall
is made will bubble up toNFTDropMarketFixedPriceSale.mintFromFixedPriceSale
and prevent the NFT from being sold.Tools Used
Text editor
Recommended Mitigation Steps
Foundation should handle cases where
call
reverts. Ifcall
reverts, then Foundation can utilizefeth.DepositFor
. To handle these cases, wrapping the call in a try statement will ensure that Foundation catches these reverts.