58287 sc high mytsharesdeposited is not updated on some token transfer

Submitted on Oct 31st 2025 at 23:58:15 UTC by @a16 for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #58287

  • Report Type: Smart Contract

  • Report severity: High

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

  • Impacts:

    • Smart contract unable to operate due to lack of token funds

    • Contract fails to deliver promised returns, but doesn't lose value

Description

Brief/Intro

The _mytSharesDeposited variable that is meant to track the amount of myt shares deposited is sometimes not updated, leading to potential DoS of deposits due to caps.

Vulnerability Details

In previous versions of the code [1], the cap was checked again the actual yieldToken balance of the AlchemistV3 contract.

    _checkState(IERC20(yieldToken).balanceOf(address(this)) + amount <= depositCap);

The code was later changed to support internal accounting using the _mytSharesDeposited variable, that is updated whenever myt are deposited/withdrawn.

However, in some parts of the code myt are transferred without a corresponding update to the _mytSharesDeposited variable, leading to an inherent mismatch between the two quantities and incorrect accounting.

For example, inside _forceRepay() myt are transferred, but _mytSharesDeposited is never decreased to reflect that.

Impact Details

Since the protocol always increases _mytSharesDeposited when myt is transferred to the AlchemistV3 contract (only through deposit) but sometime does not decrease _mytSharesDeposited when tokens are sent out of the contract, it is expected that _mytSharesDeposited will grow over time (even if the net myt balance remains about the same). This could lead to deposit DoS due to the depositCap, which is compared to the sum of _mytSharesDeposited and the deposited amount.

References

[1] Previous commit- https://github.com/alchemix-finance/v3-poc/blob/audit-contest/src/AlchemistV3.sol#L361C1-L361C89

Proof of Concept

function test_ForceRepay_ShowsSharesMismatch_BlocksDeposits() external { address trueAdmin = alchemist.admin(); address myt = address(vault); uint256 extra = 5e18;

}

Was this helpful?