sherlock-audit / 2024-04-titles-judging

1 stars 1 forks source link

Brenzee - Collection referrer never receives his share, `collectionReferrerShare` is sent to mint referrer #339

Closed sherlock-admin4 closed 2 months ago

sherlock-admin4 commented 2 months ago

Brenzee

medium

Collection referrer never receives his share, collectionReferrerShare is sent to mint referrer

Summary

When "Work" tokens are minted in Edition contract, FeeManager is responsible to distribute the fee across all the parties.

But a mistake is made in the _splitProtocolFee function, where the collectionReferrerShare is sent to the mint referrer not to the collection referrer.

Vulnerability Detail

When Edition is created in the TitlesCore contract, FeeManager.createRoute is called.

FeeManager.createRoute function specifies who is going to receive the fee and who is going to receive the collection referral fee when Work tokens are minted.

    function createRoute(
        IEdition edition_,
        uint256 tokenId_,
        Target[] calldata attributions_,
        address referrer_
    )
        external
        onlyOwnerOrRoles(ADMIN_ROLE)
        returns (Target memory receiver)
    {
        ...
        _feeReceivers[getRouteId(edition_, tokenId_)] = receiver;
        referrers[edition_] = referrer_;
    }

But whenever Work tokens are minted in Edition contract, collection referral fee is sent to mint referrer rather than to collection referrer.

    function _splitProtocolFee(
        IEdition edition_,
        address asset_,
        uint256 amount_,
        address payer_,
        address referrer_
    ) internal returns (uint256 referrerShare) {        
        ....
        _route(
            Fee({asset: asset_, amount: collectionReferrerShare}),
            // @audit But the collection referrer share is sent to mint referrer, 
            // target should be referrers[edition_]
            Target({target: referrer_, chainId: block.chainid}),
            payer_
        );
    }

Impact

Collection referrer will never receive the collection referrer share.

Code Snippet

FeeManager._splitProtocolFee

    function _splitProtocolFee(
        IEdition edition_,
        address asset_,
        uint256 amount_,
        address payer_,
        address referrer_
    ) internal returns (uint256 referrerShare) {
        // The creation and mint referrers earn 25% and 50% of the protocol's share respectively, if applicable
        uint256 mintReferrerShare = getMintReferrerShare(amount_, referrer_);
        // @audit checks how big of a share collection referrer gets
        uint256 collectionReferrerShare = getCollectionReferrerShare(amount_, referrers[edition_]);
        referrerShare = mintReferrerShare + collectionReferrerShare;

        _route(
            Fee({asset: asset_, amount: amount_ - referrerShare}),
            Target({target: protocolFeeReceiver, chainId: block.chainid}),
            payer_
        );

        _route(
            Fee({asset: asset_, amount: mintReferrerShare}),
            Target({target: referrer_, chainId: block.chainid}),
            payer_
        );

        _route(
            Fee({asset: asset_, amount: collectionReferrerShare}),
            // @audit But the collection referrer share is sent to mint referrer
            Target({target: referrer_, chainId: block.chainid}),
            payer_
        );
    }

Tool used

Manual Review

Recommendation

Make sure that the collectionReferrerShare is sent to the collection referrer. Example:

    function _splitProtocolFee(
        IEdition edition_,
        address asset_,
        uint256 amount_,
        address payer_,
        address referrer_
    ) internal returns (uint256 referrerShare) {
        // The creation and mint referrers earn 25% and 50% of the protocol's share respectively, if applicable
        address collectionReferrer = referrers[edition_];
        uint256 mintReferrerShare = getMintReferrerShare(amount_, referrer_);
        uint256 collectionReferrerShare = getCollectionReferrerShare(amount_, collectionReferrer);
        referrerShare = mintReferrerShare + collectionReferrerShare;

        _route(
            Fee({asset: asset_, amount: amount_ - referrerShare}),
            Target({target: protocolFeeReceiver, chainId: block.chainid}),
            payer_
        );

        _route(
            Fee({asset: asset_, amount: mintReferrerShare}),
            Target({target: referrer_, chainId: block.chainid}),
            payer_
        );

        _route(
            Fee({asset: asset_, amount: collectionReferrerShare}),
            Target({target: collectionReferrer, chainId: block.chainid}),
            payer_
        );
    }