Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Invalid

[M-06] Reentrancy Vulnerability in convertAccumulatedFeesToWeth Function

Summary

The convertAccumulatedFeesToWeth function in the FeeDistributionBranch contract is vulnerable to a reentrancy attack due to external calls made before updating the contract's internal state: calls to swap strategies (executeSwapExactInputSingle or executeSwapExactInput).

This sequence allows an attacker to re-enter the function during the external call, potentially manipulating the receivedWethX18 value or other state variables before _handleWethRewardDistribution is executed.

Vulnerability Details

To clarify, the presence of the onlyRegisteredSystemKeepers modifier does not mitigate the reentrancy vulnerability. It ensures only authorized keepers can call the function, but it does not prevent reentrant calls.

An attacker initiates a call to convertAccumulatedFeesToWeth, during the external call to a swap strategy, the attacker re-enters the function and manipulates state variables.

// Sample reentrancy contract
contract ReentrancyAttack {
FeeDistributionBranch target;
bool reentered = false;
constructor(address _target) {
target = FeeDistributionBranch(_target);
}
function attack(uint128 marketId, address asset, uint128 dexSwapStrategyId, bytes calldata path) external {
target.convertAccumulatedFeesToWeth(marketId, asset, dexSwapStrategyId, path);
}
// Fallback function to re-enter the function
fallback() external {
if (!reentered) {
reentered = true;
// Re-enter the target function
target.convertAccumulatedFeesToWeth(...);
}
}
}

Recommendations

Implement reentrancy guards to prevent re-entry into the function during external calls. Consider using the Checks-Effects-Interactions pattern to update the contract's state before making external calls.

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract FeeDistributionBranch is EngineAccessControl, ReentrancyGuard {
// added ReentrancyGuard
function convertAccumulatedFeesToWeth(
uint128 marketId,
address asset,
uint128 dexSwapStrategyId,
bytes calldata path
)
external
onlyRegisteredSystemKeepers
nonReentrant // added guard
{
// Current logic...
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Too generic

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.