BriVault

First Flight #52
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

`previewDeposit` Excludes Fees — Violates ERC4626 & Misleads Users

Root + Impact

Description

  • Within the OpenZeppelin's ERC4626 standard, there's a function called previewDeposit that's intended to be called by users whenever they want to have an idea of how many shares they will be getting after making a deposit.

  • Here, briVault inherits previewDeposit from OpenZeppelin's ERC4626, but does not override it. The base implementation ignores deposit fees, returning the full share amount.

  • Even EIP-4626 mentions this (under previewDeposit section):

    MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.

  • Hence, users are misled here.

    // OpenZeppelin ERC4626 (unmodified)
    function previewDeposit(uint256 assets) public view virtual returns (uint256) {
    return _convertToShares(assets, Math.Rounding.Floor);
    // ← No fee deduction!
    }

Risk

Likelihood: High

  • The wrong share amount is provided every time a user calls previewDeposit

Impact: Medium/Low

  • Users are misled about shares received

  • Actual deposit returns fewer shares

  • Breaks trust and ERC4626 compliance

Proof of Concept

  • Add this test_PreviewDeposit_IgnoresFees test in briVault.t.sol:

    function test_PreviewDeposit_IgnoresFees() public {
    vm.prank(owner);
    briVault.setCountry(countries);
    uint256 assets = 5 ether;
    // User previews deposit
    uint256 preview = briVault.previewDeposit(assets);
    console.log("previewDeposit():", preview); // 5e18
    // Actual deposit
    vm.startPrank(user1);
    mockToken.approve(address(briVault), type(uint).max);
    briVault.deposit(assets, user1);
    uint256 actual = briVault.balanceOf(user1);
    console.log("Actual shares: ", actual); // 4.925e18
    vm.stopPrank();
    assertLt(actual, preview); // ← EIP violation
    }

  • Run it using:

    forge test --mt test_PreviewDeposit_IgnoresFees -vv

  • Logs:

    Ran 1 test for test/briVault.t.sol:BriVaultTest
    [PASS] test_PreviewDeposit_IgnoresFees() (gas: 1523170)
    Logs:
    previewDeposit(): 5000000000000000000
    Actual shares: 4925000000000000000
    Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.72ms (791.36µs CPU time)

Recommended Mitigation

Override previewDeposit to include fees:

+ function previewDeposit(uint256 assets) public view override returns (uint256) {
+ uint256 fee = _getParticipationFee(assets);
+ uint256 netAssets = assets - fee;
+ return _convertToShares(netAssets, Math.Rounding.Floor);
+ }
Updates

Appeal created

bube Lead Judge 19 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Unrestricted ERC4626 functions

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!