sherlock-2025-04-burve-h06
[H-06] Fee Bypass in ValueFacet.removeValueSingle
Summary
출금 수수료를 계산하는 데 잘못된 변수를 이용하여 유저가 수수료를 지불하지 않고 출금할 수 있다.
Keyword
bug, arithmetic error, fee
Vulnerability
ValueFacet.removeValueSingle 함수를 호출하여 풀에서 출금을 할 때 수수료를 지불해야 한다. 수수료를 계산하기 위해 출금된 금액을 비율에 따라 계산해야 한다. 그런데 계산을 할 때 출금된 금액을 의미하는 변수인 realRemoved가 아니라 removedBalance를 이용한다. 이는 리턴값을 위해 정의된 변수로, 아직 초기화되지 않아 0으로 설정되어 있다. 따라서 realTax는 0으로 계산되고, 유저는 수수료를 지불하지 않으면서 출금할 수 있다.
function removeValueSingle(
address recipient,
uint16 _closureId,
uint128 value,
uint128 bgtValue,
address token,
uint128 minReceive
) external nonReentrant returns (uint256 removedBalance) {
…
(uint256 removedNominal, uint256 nominalTax) = c.removeValueSingle(
value,
bgtValue,
vid
);
@> uint256 realRemoved = AdjustorLib.toReal(token, removedNominal, false);
Store.vertex(vid).withdraw(cid, realRemoved, false);
// BUG: removedBalance is still zero here
uint256 realTax = FullMath.mulDiv(
@> removedBalance,
nominalTax,
removedNominal
);
c.addEarnings(vid, realTax);
@> removedBalance = realRemoved - realTax;
require(removedBalance >= minReceive, PastSlippageBounds());
TransferHelper.safeTransfer(token, recipient, removedBalance);
}Impact
유저가 수수료를 지불하지 않고 출금할 수 있다.
Mitigation
- uint256 realTax = FullMath.mulDiv(
- removedBalance,
- nominalTax,
- removedNominal
- );
+ // Compute the real‐world fee based on the actual tokens removed
+ uint256 realTax = FullMath.mulDiv(
+ realRemoved,
+ nominalTax,
+ removedNominal
+ );tags: bughunting, burve, smart contract, solidity, bug, arithmetic error, fee, severity high