sherlock-audit / 2024-06-boost-aa-wallet-judging

3 stars 1 forks source link

befree3x - `protocolFeeReceiver` can sometimes receive more fees than expected #418

Open sherlock-admin4 opened 2 months ago

sherlock-admin4 commented 2 months ago

befree3x

Medium

protocolFeeReceiver can sometimes receive more fees than expected

Summary

Everytime when a user claims his incentive, the protocol fee receiver will receive the whole balance of the contract BoostCore, which can be way more than expected as a user can send more ETH than the fee required.

Root Cause

The function BoostCore::_routeClaimFee is responsible to route the claim fee to the creator, referrer, and protocol fee receiver. It basically starts with the received claimeFee in ETH by sending a portion to the referer, then giving half of the rest to the boost creator. However, instead of sending what has left of the received claimeFee, it sends the whole current balance of ETH in the contract BoostCore to the protocol fee receiver.

Reference: https://github.com/sherlock-audit/2024-06-boost-aa-wallet/blob/main/boost-protocol/packages/evm/contracts/BoostCore.sol#L318


function _routeClaimFee(BoostLib.Boost storage boost, address referrer_) internal {
        if (claimFee == 0) return;
        uint256 netFee = claimFee;

        // If a referrer is provided, transfer the revshare and reduce the net fee
        if (referrer_ != address(0)) {
            uint256 referralShare = claimFee * boost.referralFee / FEE_DENOMINATOR;
            netFee -= referralShare;
            referrer_.safeTransferETH(referralShare);
        }

        // The remaining fee is split between the owner and the protocol
        boost.owner.safeTransferETH(netFee / 2);
>>      protocolFeeReceiver.safeTransferETH(address(this).balance);
}

Internal pre-conditions

NA

External pre-conditions

Attack Path

NA

Impact

There are several potential impacts:

PoC

NA

Mitigation

The protocol should only receive what has left of claimFee and send back the remaining to the end user.


function _routeClaimFee(BoostLib.Boost storage boost, address referrer_) internal {
        if (claimFee == 0) return;
        uint256 netFee = claimFee;

        // If a referrer is provided, transfer the revshare and reduce the net fee
        if (referrer_ != address(0)) {
            uint256 referralShare = claimFee * boost.referralFee / FEE_DENOMINATOR;
            netFee -= referralShare;
            referrer_.safeTransferETH(referralShare);
        }

        // The remaining fee is split between the owner and the protocol
        boost.owner.safeTransferETH(netFee / 2);
-       protocolFeeReceiver.safeTransferETH(address(this).balance);
+       protocolFeeReceiver.safeTransferETH(netFee - netFee / 2);
+       if (msg.value > claimFee) {
+           address(msg.sender).safeTransferETH(msg.value - claimFee);
+       }
}