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

Unlimited token approvals in StrategyOp contract

Summary

The StrategyOp contract grants unlimited token approvals to external contracts, potentially increasing the risk of token theft if these external contracts are compromised.

Vulnerability Details

The StrategyOp contract uses type(uint256).max to approve unlimited token spending for both the transmuter and router contracts. This practice, while convenient, exposes the contract to unnecessary risk.

Affected code:
https://github.com/Cyfrin/2024-12-alchemix/blob/5c19ee37df3aa7605bf782c9c40a482fd82adc67/src/StrategyOp.sol#L27
https://github.com/Cyfrin/2024-12-alchemix/blob/5c19ee37df3aa7605bf782c9c40a482fd82adc67/src/StrategyOp.sol#L39

// Line 27
asset.safeApprove(address(transmuter), type(uint256).max);
// Line 39
underlying.safeApprove(address(router), type(uint256).max);

These approvals are set in the constructor and _initStrategy function respectively, meaning they persist for the entire lifetime of the contract.

Impact

If the transmuter or router contracts are compromised, an attacker could potentially drain all of the approved tokens from the StrategyOp contract. While this doesn't represent an immediate vulnerability, it significantly increases the potential impact of a security breach in the approved contracts.

Tools Used

manual code review.

Recommendations

  1. Implement a more granular approval system:

    • Approve only the exact amount needed for each transaction.

    • Reset the approval to zero after each transaction.

  2. Replace the current unlimited approvals with transaction-specific approvals. For example:

function _deployFunds(uint256 _amount) internal override {
asset.safeApprove(address(transmuter), _amount);
transmuter.deposit(_amount, address(this));
asset.safeApprove(address(transmuter), 0); // Reset approval
}
function _swapUnderlyingToAsset(uint256 _amount, uint256 minOut, IVeloRouter.route[] calldata _path) internal {
underlying.safeApprove(address(router), _amount);
IVeloRouter(router).swapExactTokensForTokens(_amount, minOut, _path, address(this), block.timestamp);
underlying.safeApprove(address(router), 0); // Reset approval
}

Bellow is a finding explaining the same issue

Description

Several parts of code grant unlimited type(uint).max approvals even when it's not justifiable:

No threat is inherent to it. However, it diminishes the overall contract security and could potentially be exploited by various attack vectors.

Recommendation

It's recommended to grant approvals only for the exact amount that is anticipated to be spent.

Updates

Appeal created

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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