57328 sc low once tokelockduration is the opposite of zero in tokeautoethstrategy accumulated rewards in acctoke can be stuck

Submitted on Oct 25th 2025 at 09:36:13 UTC by @pashap9990 for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #57328

  • Report Type: Smart Contract

  • Report severity: Low

  • Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/strategies/mainnet/TokeAutoEth.sol

  • Impacts:

    • Permanent freezing of unclaimed yield

Description

Finding Description and Impact

Anyone can call MYTStrategy::claimRewards to get rewards from the TokeAutoETH strategy. Nonetheless, rewards may remain indefinitely inaccessible as Toke's rewarder stakes them in accToke when tokeLockDuration exceeds zero, leading to a perpetual yield lock due to the absence of a mechanism to claim and unstake the rewards from accToke.

https://vscode.blockscan.com/ethereum/0x60882D6f70857606Cdd37729ccCe882015d1755E

    function _getReward(address account, address recipient) internal {
        Errors.verifyNotZero(account, "account");
        Errors.verifyNotZero(recipient, "recipient");

        uint256 reward = earned(account);
        (IAccToke accToke, address tokeAddress) = (systemRegistry.accToke(), address(systemRegistry.toke()));

        // slither-disable-next-line incorrect-equality
        if (reward == 0) return;

        // if NOT toke, or staking is turned off (by duration = 0), just send reward back
        if (rewardToken != tokeAddress || tokeLockDuration == 0) {
            rewards[account] = 0;
            emit RewardPaid(account, recipient, reward);

            IERC20(rewardToken).safeTransfer(recipient, reward);
        } else if (accToke.isStakeableAmount(reward)) {
            rewards[account] = 0;
            emit RewardPaid(account, recipient, reward);
            // authorize accToke to get our reward Toke
            LibAdapter._approve(IERC20(tokeAddress), address(accToke), reward);

            // stake Toke
     @>>>       accToke.stake(reward, tokeLockDuration, recipient);
        }
    }

Textual PoC

1- WETHs are staked in TokeAutoETH. 2- New rewards are notified in the rewarder. 3- tokeLockDuration is updated by an operator. 4-The MYTStrategy::claimRewards function can be invoked by any individual, as it is permissionless. Reward tokens are staked in accToke, as tokeLockDuration is not equal to zero. 5- The function AccToke::addWETHRewards is invoked to allocate rewards to stakers. As a result, staked rewards are irrevocable. Additionally, rewards in accToke are non-redeemable due to lack of any functionality in TokeAutoEthStrategy to unstake and claim rewards from accToke.

Code Snippet

https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/strategies/mainnet/TokeAutoEth.sol

Proof of Concept

Proof of Concept

Was this helpful?