The fees charged to the feeRecipient are inconsistent between functions deposit and mint
Description
Users can choose to use either the function deposit or the function mint to deposit an asset to the vault. However, the methods by which functions deposit and mint charge the feeRecipient are inconsistent. The function deposit does not charge a deposit fee when the caller is the feeRecipient, while the function mint always charges a deposit fee regardless of the caller.
function deposit(uint256 assets_, address receiver_)
// [...]
returns (uint256 shares)
{
// [...]
// Calculate shares based on whether sender is fee recipient
if (msg.sender == feeRecipient) {
shares = _convertToShares(assets_, Math.Rounding.Floor);
} else {
// Calculate the fee in shares
uint256 feeShares = _convertToShares(
assets_.mulDiv(uint256(fees.depositFee), MAX_BASIS_POINTS, Math.Rounding.Ceil), Math.Rounding.Ceil
);
// Calculate the net shares to mint for the deposited assets
shares = _convertToShares(assets_, Math.Rounding.Floor) - feeShares;
// Mint fee shares to fee recipient
if (feeShares > 0) _mint(feeRecipient, feeShares);
}
// [...]
}function mint(uint256 shares_, address receiver_)
// [...]
returns (uint256 assets)
{
// [...]
// Calculate the deposit fee in shares
uint256 depositFee = uint256(fees.depositFee);
uint256 feeShares =
shares_.mulDiv(MAX_BASIS_POINTS, MAX_BASIS_POINTS - depositFee, Math.Rounding.Ceil) - shares_;
// Calculate the total assets required for the minted shares, including fees
assets = _convertToAssets(shares_ + feeShares, Math.Rounding.Ceil);
// [...]
}Impact
If the feeRecipient is depositing on behalf of a receiver, then, using the same amount of the asset, the receiver will receive more shares if the function deposit is used.
Recommendations
Consider unifying the way these two functions charge the feeRecipient and updating functions previewDeposit and previewMint accordingly.
Remediation
This issue has been acknowledged by Blueprint Finance, and fixes were implemented in the following commits: