For the complete documentation index, see llms.txt. This page is also available as Markdown.

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 V3

  • 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?