56336 sc insight stargateethpoolstrategy deallocate would emit false deallocating loss event in some cases
Submitted on Oct 14th 2025 at 17:17:36 UTC by @farismaulana for Audit Comp | Alchemix V3
Report ID: #56336
Report Type: Smart Contract
Report severity: Insight
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/strategies/optimism/StargateEthPoolStrategy.sol
Impacts:
Description
Brief/Intro
the _deallocate amount param is capped to lpBalance if the amount param is greater than the contract balance. but the check ethRedeemed < amount is using amount for comparison which is not always the amount used for redeem because the above cap mechanism.
Vulnerability Details
function _deallocate(uint256 amount) internal override returns (uint256) {
// Compute LP needed ∝ TVL to withdraw `amount` underlying
// For Stargate, LP tokens are 1:1 with underlying
// So we can just redeem the amount directly
uint256 lpBalance = lp.balanceOf(address(this));
uint256 lpNeeded = amount; // 1:1 ratio
// Cap at available LP balance
if (lpNeeded > lpBalance) {
@> lpNeeded = lpBalance;
}
// Redeem LP to native ETH, then wrap back to WETH
lp.approve(address(pool), lpNeeded);
uint256 ethBalanceBefore = address(this).balance;
@> pool.redeem(lpNeeded, address(this));
uint256 ethBalanceAfter = address(this).balance;
uint256 ethRedeemed = ethBalanceAfter - ethBalanceBefore;
// @audit
if (ethRedeemed < amount) {
emit StrategyDeallocationLoss("Strategy deallocation loss which includes rounding loss.", amount, ethRedeemed);
}
here we can see that if the amount assigned to lpNeeded. for some case where it is capped to lpBalance, the redeem call would use this lpBalance that always result in lower ethRedeemed than the amount thus it would always emitting the event which is not necessarily true.
Impact Details
possibly emitting deallocation loss when it is not
References
https://github.com/alchemix-finance/v3-poc/blob/b2e2aba046c36ff5e1db6f40f399e93cd2bdaad0/src/strategies/optimism/StargateEthPoolStrategy.sol#L73-L74
Proof of Concept
Proof of Concept
contract deallocating 100 LP amount
currently the contract is having 99.8 LP amount
cap the amount, and call
pool.redeemusing 99.8 LP, and get 99.8 ethercheck if the
ethRedeemed < amountwhich is99.8 < 100emit the deallocation loss event, even though that is all LP token the contract have and no deallocation loss happen
Was this helpful?