Closed code423n4 closed 2 years ago
If someone sends an invalid request to the fee burner (such as two ETH pools), then it is expected that the transaction should fail. That is the intended behaviour.
The FeeBurner
holds no ETH as part of normal operation. There is nothing to drain.
Have to agree with the sponsor, if the function is called with the goal of burning ETH twice, the first time the burn will burn all available balance, and then the second time a revert will happen as no ETH is there to be sent to the SwapperRouter.
The contract has no tokens nor balance as such the POC is invalidated
Lines of code
FeeBurner.sol#L43-L88
Vulnerability details
Impact
The
burnToTarget
function inFeeBurner.sol
allows any array oftokens_
to be used. If thetokens_
array contains more than 1 zero address, theswapAll
function for theswapperRouter_
will be called more than once with the samemsg.value
. After the firstswapAll
call, theFeeBurn.sol
contract will start to lose ETH.Proof of Concept
Let's say the
FeeBurner.sol
holds 5 ETH and an attacker callsburnToTarget
with atokens_
array of 2 zero addresses and amsg.value
of 5 ETH, increasing the contract's total balance to 10 ETH.Assuming
targetLpToken
is valid, the first if block in the for loop will be triggered sincetoken_ == address(0)
.msg.value
is non-zero so theswapAll
function is called with msg.value to swap the ETH for WETH. The contract now has approximately 5 ETH again and 5 WETH.After the first swap, the loop continues and the first if block is triggered again. Since msg.value is still 5 ether,
swapAll
is called. The contract will use its remaining 5 ETH and receive 5 WETH. The contract now has a balance of approximately 0 ETH and 10 WETH.The for loop is now finished and all the WETH in the contract is then swapped for the underlying token of the target pool.
FeeBurner.sol
is left with approximately 0 ETH and 0 WETH.Recommended Mitigation Steps
The if block should not trigger if
burningETH_
is true. Consider changing the if condition toaddress(token_) == address(0) && !burningETH_
so that ETH is not swapped more than once.