sherlock-audit / 2024-04-titles-judging

9 stars 6 forks source link

ZanyBonzy - Protocol doesn't validate that users send fees #259

Closed sherlock-admin4 closed 4 months ago

sherlock-admin4 commented 4 months ago

ZanyBonzy

medium

Protocol doesn't validate that users send fees

Summary

Protocol doesn't validate that user pays fees in ETH, causing that users can mint without paying fees, or paying little amount of fees.

Vulnerability Detail

Amount sent by users is not validated against the amount required to be sent which can lead to users sending little or no eth as fees while minting. This will lead to loss of funds as protocol will not get needed fees for minting. When users mint, they're sometimes required to pay fees, for minting. The ETH sent as fees is collected through the collectMintFee function.

    function mint(
        address to_,
        uint256 tokenId_,
        uint256 amount_,
        address referrer_,
        bytes calldata data_
    ) external payable override {
        // wake-disable-next-line reentrancy
        FEE_MANAGER.collectMintFee{value: msg.value}(
            this, tokenId_, amount_, msg.sender, referrer_, works[tokenId_].strategy
        );

        _issue(to_, tokenId_, amount_, data_);
        _refundExcess();
    }

The _collectMintFee function collects and splits the fees in its required shares. Notice that no validation is made that msg.value sent == fee.amount

    function _collectMintFee(
        IEdition edition_,
        uint256 tokenId_,
        uint256 amount_,
        address payer_,
        address referrer_,
        Fee memory fee_
    ) internal {
        if (fee_.amount == 0) return;

        // For free mints:
        // - Protocol Share = 1/3 of flat fee
        // - Edition Share = 2/3 of flat fee
        //
        // For priced mints:
        // - Protocol Share = 100% of flat fee, shared as follows:
        // - Edition Share = 100% of creator-specified mint cost, 0% of flat fee
        //
        // In both cases, the protocol and edition shares may be split as follows:
        // - Protocol Share
        //   - If a referred mint, mint referrer gets 50% of the protocol share
        //   - If a referred collection, collection referrer gets 25% of the protcol share
        //   - Protocol fee receiver gets the remainder of the protocol share
        // - Edition Share
        //   - Attributions equally split 25% of the edition share, if applicable
        //   - Creator gets the remainder of the edition share

        uint256 protocolFee = protocolFlatFee * amount_;
        uint256 protocolShare;
        if (fee_.amount == protocolFee) {
            protocolShare = protocolFee * protocolFeeshareBps / MAX_BPS;
        } else {
            protocolShare = protocolFee;
        }

        _route(
            Fee({asset: fee_.asset, amount: fee_.amount - protocolShare}),
            _feeReceivers[getRouteId(edition_, tokenId_)],
            payer_
        );

        uint256 referrerShare =
            _splitProtocolFee(edition_, fee_.asset, protocolShare, payer_, referrer_);
        emit FeeCollected(address(edition_), tokenId_, fee_.asset, fee_.amount, referrerShare);
    }

The fees get routed and transferred to the required addresses.

    function _route(Fee memory fee_, Target memory feeReceiver_, address feePayer_) internal {
        // Cross-chain fee routing is not supported yet
        if (block.chainid != feeReceiver_.chainId) revert NotRoutable();
        if (fee_.amount == 0) return;

        _transfer(fee_.asset, fee_.amount, feePayer_, feeReceiver_.target);
    }
...
    function _transfer(address asset_, uint256 amount_, address from_, address to_) internal {
        if (asset_ == ETH_ADDRESS) {
            to_.safeTransferETH(amount_);
        } else {
            asset_.safeTransferFrom(from_, to_, amount_);
        }
    }

A malicious user can simply mint editions without sending any ETH or sending very little, less than he's supposed to send.

Impact

Loss of funds for protocol due to free minting.

Code Snippet

https://github.com/sherlock-audit/2024-04-titles/blob/d7f60952df22da00b772db5d3a8272a988546089/wallflower-contract-v2/src/fees/FeeManager.sol#L366 https://github.com/sherlock-audit/2024-04-titles/blob/d7f60952df22da00b772db5d3a8272a988546089/wallflower-contract-v2/src/editions/Edition.sol#L236

Tool used

Manual Code Review

Recommendation

Validate that msg.value sent is equal to the fee.amount