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

Lack of Router Input Validation in `claimAndSwap` Function in `StrategyOp.sol`

Summary

The claimAndSwap function in StrategyOp.sol does not validate the _path input provided to the router.

This allows malicious or erroneous paths to be passed, potentially leading to unauthorized or unintended token swaps, resulting in financial loss or disrupted protocol functionality.

Vulnerability Details

The claimAndSwap function is designed to claim WETH from the transmuter and swap it for alETH using a provided path via the router.

However, the function does not validate that the _path input starts with the underlying token (WETH) and ends with the asset token (alETH).

This lack of validation exposes the function to potential misuse:

A malicious keeper could pass a _path that swaps WETH for unintended tokens, misdirecting funds.

function claimAndSwap(
uint256 _amountClaim,
uint256 _minOut,
IVeloRouter.route[] calldata _path
) external onlyKeepers {
transmuter.claim(_amountClaim, address(this));
uint256 balBefore = asset.balanceOf(address(this));
_swapUnderlyingToAsset(_amountClaim, _minOut, _path);
uint256 balAfter = asset.balanceOf(address(this));
require((balAfter - balBefore) >= _minOut, "Slippage too high");
transmuter.deposit(asset.balanceOf(address(this)), address(this));
}

The _path array passed to _swapUnderlyingToAsset is directly used in the router call without any validation:

function _swapUnderlyingToAsset(
uint256 _amount,
uint256 minOut,
IVeloRouter.route[] calldata _path
) internal {
require(minOut > _amount, "minOut too low");
uint256 underlyingBalance = underlying.balanceOf(address(this));
require(underlyingBalance >= _amount, "not enough underlying balance");
IVeloRouter(router).swapExactTokensForTokens(_amount, minOut, _path, address(this), block.timestamp);
}

Impact

A malicious keeper could execute swaps for tokens other than the intended alETH, potentially draining funds.

Recommendations

Validate the _path array to ensure it adheres to the expected structure:

Ensure _path[0].from matches underlying (WETH).

Ensure _path[_path.length - 1].to matches asset (alETH).

Updated claimAndSwap function:

function claimAndSwap(
uint256 _amountClaim,
uint256 _minOut,
IVeloRouter.route[] calldata _path
) external onlyKeepers {
+ require(_path[0].from == address(underlying), "Invalid start token in path");
+ require(_path[_path.length - 1].to == address(asset), "Invalid end token in path");
transmuter.claim(_amountClaim, address(this));
uint256 balBefore = asset.balanceOf(address(this));
_swapUnderlyingToAsset(_amountClaim, _minOut, _path);
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: Non-acceptable severity
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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