hats-finance / Intuition-0x538dbadc50cc87b281cd655f1edbc6ebda02a66a

The smart contracts of the Intuition protocol v1.
https://intuition.systems
Other
0 stars 1 forks source link

Certainly. Here's a report for the issue you've identified: #77

Open hats-bug-reporter[bot] opened 2 days ago

hats-bug-reporter[bot] commented 2 days ago

Github username: -- Twitter username: -- Submission hash (on-chain): 0x45af594e37907786efc19eea5046d4b897518936ba6dc1ee0e011e4b1bfa26dd Severity: high

Description: Description\ In the getRedeemAssetsAndFees function of the EthMultiVault contract, there's an inconsistency in the order of fee calculations. The exit fee is calculated based on the asset amount after the protocol fee has been deducted, rather than on the full asset amount before any fees. This approach may lead to lower exit fees than expected and could potentially be exploited.

Attack Scenario\ While not a direct attack vector, this inconsistency can lead to the following issues:

  1. Users redeeming large amounts of shares could pay disproportionately lower exit fees.
  2. The protocol may collect less in exit fees than intended over time.
  3. This could be exploited in combination with other mechanisms to maximize returns at the expense of the protocol or other users.

For example:

  1. A user identifies this discrepancy.
  2. They wait for a situation where the protocol fee is high.
  3. They perform a large redemption, benefiting from a lower exit fee calculated on the post-protocol fee amount.
  4. This could be repeated to consistently pay lower exit fees on large redemptions.

Attachments

https://github.com/hats-finance/Intuition-0x538dbadc50cc87b281cd655f1edbc6ebda02a66a/blob/b2e422ff0c3e3729e58d2699fdf2ef8699fbd172/src/EthMultiVault.sol#L1153

  1. Revised Code File (Optional)

    
    function getRedeemAssetsAndFees(uint256 shares, uint256 id) public view returns (uint256, uint256, uint256, uint256) {
    uint256 remainingShares = vaults[id].totalShares - shares;
    
    uint256 assetsForReceiverBeforeFees = convertToAssets(shares, id);
    uint256 protocolFee;
    uint256 exitFee;
    
    if (paused()) {
        exitFee = 0;
        protocolFee = 0;
    } else if (remainingShares == generalConfig.minShare) {
        exitFee = 0;
        protocolFee = protocolFeeAmount(assetsForReceiverBeforeFees, id);
    } else {
        // Calculate exit fee before protocol fee
        exitFee = exitFeeAmount(assetsForReceiverBeforeFees, id);
        protocolFee = protocolFeeAmount(assetsForReceiverBeforeFees, id);
    }
    
    uint256 totalUserAssets = assetsForReceiverBeforeFees;
    uint256 assetsForReceiver = assetsForReceiverBeforeFees - exitFee - protocolFee;
    
    return (totalUserAssets, assetsForReceiver, protocolFee, exitFee);
    }