sherlock-2025-07-mellow-h05
[H-05] Incorrect performance fee calculation in FeeManager
Summary
수수료 계산 공식이 잘못되어 수수료를 실제보다 많이 뗄 수 있다.
Keyword
arithmetic error, logic flaw, fee
Vulnerability
function calculateFee(address vault, address asset, uint256 priceD18, uint256 totalShares)
public
view
returns (uint256 shares)
{
FeeManagerStorage storage $ = _feeManagerStorage();
if (asset == $.baseAsset[vault]) {
uint256 minPriceD18_ = $.minPriceD18[vault];
if (priceD18 < minPriceD18_ && minPriceD18_ != 0) {
@> shares = Math.mulDiv(minPriceD18_ - priceD18, $.performanceFeeD6 * totalShares, 1e24);
}
}
uint256 timestamp = $.timestamps[vault];
if (timestamp != 0 && block.timestamp > timestamp) {
shares += Math.mulDiv(totalShares, $.protocolFeeD6 * (block.timestamp - timestamp), 365e6 days);
}
}이 공식은 가격 차이(minPriceD18_ - priceD18)를 totalShares와 곱하여 수수료 주식 수를 계산하고 있다. 이 공식 자체가 잘못되었다.
예를 들어 다음과 같은 상황이라고 가정하자.
- 기존 최소 가격
minPriceD18 = 100e18, 새로운 가격priceD18 = 90e18, 수수료 비율performanceFee = 1e5(10%) 라고 하자. feeShare = 10e18 * 1e5 * totalShare / 1e24 = totalShare이다.- 즉, 수수료 share가 total share 와 같게 된다.
Impact
수수료가 잘못 계산된다.
Mitigation
가격 변화로 인한 share 를 계산하기 위해서는 분모에 priceD18 를 포함시켜야 한다. 가격 변화량 * (수수료 % / 1e6) * 전체 share / 가격 으로 계산해야 한다.
- shares = Math.mulDiv(minPriceD18_ - priceD18, $.performanceFeeD6 * totalShares, 1e24);
+ shares = Math.mulDiv(minPriceD18_ - priceD18, $.performanceFeeD6 * totalShares, 1e6 * priceD18);Memo
가격을 1e18로 잘못 가정한 것이 문제인 것 같다. (기존 1e24로 나눔)
tags: bughunting, mellow, smart contract, solidity, severity high, arithmetic error, logic flaw, fee