Rewards generated by the TokeAutoEth strategy are claimed into the MYT vault (address(MYT)). Once received or staked under the MYT address, these rewards (TOKE token) cannot be withdrawn, transferred, or reallocated. As a result, all rewards are permanently stuck in the MYT contract.
Description
When claimRewards() is called, the strategy executes:
MYTStrategy.sol::functionclaimRewards()publicvirtualreturns(uint256){require(!killSwitch,"emergency");_claimRewards();}It calls into TokeAutoEth.sol::function_claimRewards()internaloverridereturns(uint256rewardsClaimed){ rewardsClaimed = rewarder.earned(address(this));>> rewarder.getReward(address(this),address(MYT),false);// transfer all TOKE token rewards to morpho vault or get staked on myt address}
The Tokemak rewarder then either transfers the TOKE tokens or stakes them with recipient = address(MYT):
[Link to Tokemak rewarder code]](https://github.com/Tokemak/v2-core-pub/blob/de163d5a1edf99281d7d000783b4dc8ade03591e/src/rewarders/AbstractRewarder.sol#L306C4-L331C6)
Since the MYT vault has no functionality to transfer, withdraw, or re-allocate these TOKE rewards, all claimed rewards becomes permanently locked.
Additionally, anyone can call claimRewards(), meaning the freeze can occur at any time, even if rewards are small and unintended.
Impact
All TOKE rewards generated by the strategy become locked into myt.
Recommendation
Claim rewards to the strategy instead of the MYT vault:
Then implement appropriate handling in the strategy:
Optionally swap to underlying asset, OR sends to owner
Introduce unstake() too to get staked toke.
Proof of Concept
Proof of Concept
PoC Summary
Since the real rewarder contract on mainnet distributes rewards based on live protocol state, the test environment cannot naturally reproduce accrued rewards. To demonstrate the issue in isolation, we replaced the rewarder contract implementation at its address using vm.etch and pointed its rewardToken storage slot to a mock ERC20 token. The mock rewarder is intentionally minimal and always returns a fixed reward amount (5e18) for earned() and sends that amount in getReward().
By doing this, we simulate the presence of claimable rewards without altering the whole rewarder logic. When claimRewards() is executed, the adapter puts recipient as myt, and then those reward token(TOKE token) will always stuck in vault/MYT.
Add below test case and interfaces into TokeAutoEthStrategy.t.sol:
run by forge test --mt test_rewards_stuck_into_myt -vvvv