DeFiFoundrySolidity
16,653 OP
View results
Submission Details
Severity: high
Invalid

Adding a ReentrancyGuard to

Summary

Vulnerability Details

Issue: Reentrancy Risk in Fund Management Functions

The following functions are vulnerable to reentrancy attacks:

  1. _deployFunds(uint256 _amount)

    • Calls transmuter.deposit(), which interacts with an external contract. Without a reentrancy guard, a malicious contract could exploit this by calling back into the function before state updates are complete.

  2. claimAndSwap(uint256 _amountClaim, uint256 _minOut, uint256 _routeNumber)

    • This function involves external interactions with the transmuter.claim() and a Curve Router via router.exchange(). The absence of a guard allows attackers to recursively exploit state changes and drain funds.

  3. _freeFunds(uint256 _amount)

    • Calls transmuter.withdraw(), which is another external interaction prone to reentrancy risks.

Impact

The vulnerability poses a high severity risk with the following potential impacts:

  1. Fund Theft: Malicious actors could recursively call vulnerable functions to withdraw more funds than intended.

  2. State Corruption: Incomplete execution of state changes could lead to inconsistencies in balances and other critical contract variables.

  3. Ecosystem Exploitation: If deployed on mainnet, the issue could damage user trust and result in significant financial losses for the protocol.

Example Scenario:

  • A malicious contract calls claimAndSwap() to initiate a token swap, then recursively invokes itself during external calls to withdraw more funds than permitted.

Tools Used

Recommendations

Implement Reentrancy Guard:
Add OpenZeppelin’s ReentrancyGuard to the contract and apply the nonReentrant modifier to all vulnerable functions.

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract StrategyMainnet is BaseStrategy, ReentrancyGuard {
...
function _deployFunds(uint256 _amount) internal override nonReentrant {
transmuter.deposit(_amount, address(this));
}
function claimAndSwap(
uint256 _amountClaim,
uint256 _minOut,
uint256 _routeNumber
) external onlyKeepers nonReentrant {
transmuter.claim(_amountClaim, address(this));
uint256 balBefore = asset.balanceOf(address(this));
require(_minOut > _amountClaim, "minOut too low");
router.exchange(
routes[_routeNumber],
swapParams[_routeNumber],
_amountClaim,
_minOut,
pools[_routeNumber],
address(this)
);
uint256 balAfter = asset.balanceOf(address(this));
require((balAfter - balBefore) >= _minOut, "Slippage too high");
transmuter.deposit(asset.balanceOf(address(this)), address(this));
}
...
}
Updates

Appeal created

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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