Root: The custom _convertToShares function calculates share prices based on the raw token balance of the contract (asset.balanceOf(address(this))), which can be artificially inflated by direct transfer calls (donations).
Impact: An early depositor can manipulate the share price to be extremely high. Subsequent depositors will then receive far fewer shares than the fair value of their assets, and in minimal configurations, can receive zero shares, effectively losing their entire deposit to the vault. This breaks the fundamental fairness of the ERC4626 vault standard.
A core promise of an ERC4626 vault is that the number of shares minted should fairly represent the value of the assets deposited. The BriVault contract implements a custom share calculation mechanism that is vulnerable to a well-known inflation attack.
The _convertToShares function uses the contract's live token balance to determine the price of a share. An attacker can exploit this by:
Depositing a very small amount of assets to mint a small number of initial shares (e.g., 1 share for 1 wei).
Directly transferring a large amount of the underlying asset to the contract address. This inflates the asset.balanceOf(address(this)) without creating any new shares.
As a result, the calculated price per share becomes astronomically high.
When a legitimate user (the victim) subsequently makes a large deposit, the Math.mulDiv calculation in _convertToShares rounds down significantly due to the manipulated ratio.
Under minimal fee/deposit configurations: The victim can receive zero shares, losing their entire deposit.
Under the project's default configurations: The victim receives a positive but unfairly small number of shares, meaning they have significantly overpaid for their portion of the vault.
This vulnerability undermines the economic safety of the vault and can lead to a direct loss of value for users.
Likelihood: High
This is a well-documented attack vector for non-standard ERC4626 implementations. It can be executed by any user who is able to be the first or an early depositor.
Impact: High
Significant Financial Loss for Users: Users can lose a substantial portion or, in some cases, all of their deposited funds' value by receiving far too few shares or zero shares.
Broken Core Vault Mechanics: The vault fails its primary function of fairly representing deposited assets with tokenized shares, destroying trust in the protocol's accounting.
The following tests validate the vulnerability under two different configurations, demonstrating its severity and practicality.
Test A (test_donationAttack_minimalConfig_victimGetsZeroShares) proves that with minimal fees and deposit requirements, the victim receives zero shares, leading to a complete loss of their deposited assets.
Test B (test_donationAttack_defaultConfig_victimGetsPositiveButReducedShares) proves that even under the project's default settings, the victim receives an unfairly low number of shares, demonstrating the price manipulation.
Test Results:
The contract should not use a custom, vulnerable share calculation. It should either adopt the battle-tested OpenZeppelin ERC4626 implementation, which includes mitigations for this attack, or implement similar protections.
Recommended Fix: Align with Secure ERC4626 Practices
Remove the custom _convertToShares function.
Override totalAssets() to correctly report the vault's underlying assets.
Use the inherited, secure _deposit function from the OpenZeppelin contract.
Add a critical check to ensure that a deposit results in at least one share.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.