58129 sc high missing mytsharesdeposited update in forcerepay causes accounting inconsistency which can dos deposit and liquidation

Submitted on Oct 30th 2025 at 20:37:30 UTC by @gizzy for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #58129

  • Report Type: Smart Contract

  • Report severity: High

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

  • Impacts:

    • Protocol insolvency

Description

Summary

The _forceRepay() function collects and transfers protocol fees and creditToYield but fails to update _mytSharesDeposited, unlike repay() and burn() which properly decrement this accounting variable. This creates a growing discrepancy between actual token balances and recorded deposits, breaking a critical system invariant.

Vulnerability Details

The Issue

_mytSharesDeposited tracks the total yield tokens deposited in the Alchemist and is used for critical calculations like deposit caps and total value locked (TVL). When protocol fees are collected, tokens leave the contract and must be deducted from this counter.

Correct implementation in repay():

Buggy implementation in _forceRepay():

Attack Path

This happens normally from protocol usage.

  1. User's position becomes undercollateralized (collateralizationRatio <= collateralizationLowerBound)

  2. User's account has earmarked debt (account.earmarked > 0)

  3. Anyone calls liquidate(accountId) on the user's position

  4. _liquidate() calls _forceRepay() to repay the earmarked debt

  5. Protocol fee and creditToYield transferred out, but _mytSharesDeposited is NOT decremented

  6. Over time, _mytSharesDeposited becomes increasingly inflated

Impact

1. Broken Deposit Cap Enforcement

The inflated _mytSharesDeposited will cause deposits to hit the cap prematurely, blocking legitimate deposits even when the actual balance is lower.

2. Incorrect TVL Calculations

This inflated TVL affects liquidation calculations, potentially preventing liquidations when the system is actually undercollateralized globally.

3. Compounding Issue

Each liquidation with earmarked debt increases the discrepancy. Over time with many liquidations, the accounting error grows unbounded.

Reference

https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/AlchemistV3.sol#L771C8-L780C10

Update _forceRepay() to decrement _mytSharesDeposited consistently with repay() and burn():

Note: Both creditToYield (sent to transmuter) AND protocolFeeTotal (sent to fee receiver) must be decremented since both amounts leave the contract.

Proof of Concept

Proof of Concept

Update the AlchemistV3.sol _mytSharesDeposited to public for test to run

uint256 public _mytSharesDeposited;

Copy and paste in AlchemistV3.t

Was this helpful?