56494 sc insight gas optimization redundant external calls in strategy deallocate functions
Submitted on Oct 16th 2025 at 19:36:39 UTC by @Snuggle for Audit Comp | Alchemix V3
Report ID: #56494
Report Type: Smart Contract
Report severity: Insight
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/strategies/arbitrum/EulerARBWETHStrategy.sol
Impacts:
Description
Brief/Intro
Multiple strategy contracts in the Alchemix V3 protocol contain inefficient gas usage patterns in their _deallocate functions. These contracts perform redundant external calls to TokenUtils.safeBalanceOf() when they already have the balance value cached in memory. This leads to unnecessary gas consumption without providing additional security benefits. The same issue exists across 14 strategy contracts across all networks.
Vulnerability Details
Multiple strategy contracts contain redundant external calls in their
_deallocatefunctionsThe pattern involves calling
TokenUtils.safeBalanceOf()twice when the balance value is already available in memoryThis affects 14 strategy contracts across Mainnet, Arbitrum, and Optimism networks
Example from EulerARBWETHStrategy:
The function calls
TokenUtils.safeBalanceOf()on line 37 to getwethBalanceAfterThen it calls
TokenUtils.safeBalanceOf()again on line 42 for the require statementThe
wethBalanceAftervariable already contains the exact same value needed for the require checkNo state changes occur between these two calls that would affect the balance
Impact Details
Gas inefficiency: Each redundant
TokenUtils.safeBalanceOf()call consumes unnecessary gas for staticcallCode maintainability: Redundant external calls make the function less efficient and harder to optimize
No security benefit: The second call provides no additional security since the balance value is already cached
Pattern repetition: The same inefficient pattern exists across multiple strategy contracts
Severity: Insight (gas optimization issue, not a security vulnerability)
Affected Contracts List
Mainnet Strategies (7 contracts):
src/strategies/mainnet/EulerUSDCStrategy.solsrc/strategies/mainnet/EulerWETHStrategy.solsrc/strategies/mainnet/MorphoYearnOGWETH.solsrc/strategies/mainnet/PeapodsETH.solsrc/strategies/mainnet/PeapodsUSDC.solsrc/strategies/mainnet/TokeAutoEth.solsrc/strategies/mainnet/TokeAutoUSDStrategy.sol
Arbitrum Strategies (4 contracts):
src/strategies/arbitrum/EulerARBWETHStrategy.solsrc/strategies/arbitrum/EulerARBUSDCStrategy.solsrc/strategies/arbitrum/AaveV3ARBUSDCStrategy.solsrc/strategies/arbitrum/AaveV3ARBWETHStrategy.sol
Optimism Strategies (3 contracts):
src/strategies/optimism/MoonwellUSDCStrategy.solsrc/strategies/optimism/MoonwellWETHStrategy.solsrc/strategies/optimism/StargateEthPoolStrategy.sol
Total: 14 strategy contracts affected across all networks
Recommendation
Replace redundant external calls with cached values. The same optimization pattern applies to all 14 affected contracts:
Example Fix for EulerARBWETHStrategy.sol:
Key Change: Replace require(TokenUtils.safeBalanceOf(address(weth), address(this)) >= amount, ...) with require(wethBalanceAfter >= amount, ...)
This optimization pattern should be applied to all 14 affected contracts listed above, maintaining the same security guarantees while eliminating redundant gas consumption.
Proof of Concept
Proof of Concept
Steps to Reproduce:
Call
_deallocatefunction in any affected strategy contract with any valid amountObserve that
TokenUtils.safeBalanceOf()is called multiple times for the same balance checkVerify that the cached balance value could be used instead of making additional external calls
Was this helpful?