sherlock-audit / 2024-04-titles-judging

9 stars 6 forks source link

cducrest-brainbot - Fee receivers can revert on receive to deny mints #241

Closed sherlock-admin4 closed 4 months ago

sherlock-admin4 commented 4 months ago

cducrest-brainbot

high

Fee receivers can revert on receive to deny mints

Summary

The FeeManager contract uses to_.safeTransferETH(amount_) to send fee amounts to fee recipients which checks whether the transfer was successful. Recipients can selectively revert in their receive function to deny a mint.

Vulnerability Detail

The function used to transfer eth in FeeManager uses safeTransferETH():

    function _transfer(address asset_, uint256 amount_, address from_, address to_) internal {
        if (asset_ == ETH_ADDRESS) {
            to_.safeTransferETH(amount_);
        } else {
            asset_.safeTransferFrom(from_, to_, amount_);
        }
    }

This function is from Solady's SafeTransferLib library and reverts when the call is not successful:

    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

Impact

Any fee receiver can selectively deny a mint that pays fees. Fee recipients are the protocol defined fee recipient, the mint referrer, the edition referrer, the creator, and the 0xSplit contract.

This can be done to reserve the last mint of tokens before reaching the maxSupply value of a work as minting the last available tokens of a collection brings scarcity and can be seen as valuable. That way, a fee receiver sees that the last tokens are about to be minted, prevents the mint by reverting in their receive() functions and mint the tokens for themselves to sell later.

Another critical impact is that an edition's referrer can DOS any mint on an edition for a long time as it receives part of the protocol fees on any mints and cannot be easily updated by the edition's creator. The edition's referrer is set inside the createRoute() function which is only called by TitlesCore on edition creation. This function can also be called by the ADMIN_ROLE and updating the referrer would require on-chain admin intervention.

Other fee recipients may DOS the mint but are easier to update / less incentivized to do so.

Code Snippet

https://github.com/sherlock-audit/2024-04-titles/blob/d7f60952df22da00b772db5d3a8272a988546089/wallflower-contract-v2/src/fees/FeeManager.sol#L461-L467

https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol

Tool used

Manual Review

Recommendation

Make fee recipients withdraw fees from the contract instead of sending them directly or use Solady's forceSafeTransferETH() or trySafeTransferETH().