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():
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.
cducrest-brainbot
high
Fee receivers can revert on receive to deny mints
Summary
The
FeeManager
contract usesto_.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()
:This function is from Solady's
SafeTransferLib
library and reverts when the call is not successful: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 theirreceive()
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 byTitlesCore
on edition creation. This function can also be called by theADMIN_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()
ortrySafeTransferETH()
.