DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Share Ratio Manipulation via Direct Token Deposits and 1e8 Initial Minting

Summary

The vulnerability arises from the use of an inflated scaling factor (1e8) when minting the initial shares, combined with the reliance on the contract's collateral balance (via collateralToken.balanceOf(address(this))) to calculate new shares. An attacker can exploit this by transferring extra tokens directly to the contract. This manipulation inflates the reported collateral balance, resulting in subsequent depositors receiving fewer shares per token deposited and allowing the attacker to control a disproportionate share of the vault. This violates the invariant that a depositor’s share value should never decrease because of the actions of other participants. Also just one user will control a large amoun tof the shares just by depositing first.

Vulnerability Details

Infected Code Snippet – Minting Shares

When the vault is empty, the first deposit mints shares by multiplying the deposit amount by 1e8:

if (totalShares == 0) {// A small deposit is amplified by 1e8, inflating the share count
_shares = depositInfo[depositId].amount * 1e8; }
else {
uint256 totalAmountBefore;
if (positionIsClosed == false && _isLongOneLeverage(beenLong)) {
totalAmountBefore = IERC20(indexToken).balanceOf(address(this)) - amount;
} else {
// if positionIsClosed = true, we calcute the totalAmountBefore like this:
// collateralToken.balanceOf(address(this)) - amount
totalAmountBefore = _totalAmount(prices) - amount;
}
if (totalAmountBefore == 0) totalAmountBefore = 1;
_shares = amount * totalShares / totalAmountBefore; }

This logic means that an attacker depositing a minimal amount can obtain an enormous number of shares relative to the actual collateral value.

PoC

For the sake of an easier explanation we will assume the minDepositAmount is 0.5

For this attack path to work positionIsClosed = true

Initial Deposit by Attacker:
The attacker deposits 1 token when totalShares == 0 and receives:

1 token * 1e8 = 100,000,000 shares.
  • Direct Transfer Manipulation:
    The attacker then transfers an additional 9 tokens directly to the contract. The contract’s balance becomes 10 tokens.

  • Honest Depositor's Deposit:
    An honest depositor later deposits 1 token. At that time, the contract calculates the total amount before the deposit as:

    totalAmountBefore = (collateral balance after deposit) - depositAmount =
    (11 tokens - 1 token) = 10 tokens.

    New shares are then minted as:

    newShares = 1 token * 100,000,000 / 10 tokens = 10,000,000 shares.
  • Resulting Impact:

    • Attacker’s Shares: 100,000,000

    • Honest Depositor’s Shares: 10,000,000

    • Total Shares: 110,000,000

    Upon withdrawal, the attacker controls ~90.9% of the vault assets despite both parties depositing 1 token each.

Impact

The vulnerability centers on two critical flaws working together to create a severe exploitation vector:

  • Arbitrary 1e8 Share Scaling: By depositing even a minimal amount, the first user receives an extraordinarily high number of shares (scaled by 1e8), granting them disproportionate control over the vault.

  • Contract Balance Dependency: The contract calculates shares based on collateralToken.balanceOf(address(this)), which can be manipulated by directly transferring tokens to the contract outside the deposit function. This design flaw means any tokens in the contract—even those not properly accounted for through deposits—affect share calculations.

  • Manipulation of Share Value: When the attacker directly transfers additional tokens to the contract, they artificially inflate the contract's balance, causing subsequent depositors to receive fewer shares per token since the share calculation relies on the total balance rather than tracked deposits.

  • Theft of Investment Value: The attacker can strategically time their withdrawal to extract significantly more value than their actual contribution warrants, effectively stealing from other users.

  • MEV Exploitation: A sophisticated attacker could monitor the mempool for large incoming deposits, front-run these transactions with their withdrawal, and then back-run with a new deposit at the manipulated (more favorable) share ratio.

  • Destruction of Trust: Such manipulation fundamentally breaks the core invariant of the vault system—that a user's share value should represent a fair proportion of their contributed assets—making the protocol unusable for legitimate purposes.

Tools Used

Manual review

Recommendations

Use a dedicated variable to track deposits rather than relying solely on collateralToken.balanceOf(address(this)). This prevents unauthorized tokens from affecting share calculations.

When first initializing the contract, increase the total number of shares to 1e8 instead of minting them to the first depositor, that way the contract won't suffer any rounding issues and the shares will be calculated fairly.

Updates

Lead Judging Commences

n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

invalid_collateral_balanceOf_donation

Prevent tokens from getting stuck. This is a simple donation to every shareholder, and therefore, every share has more value (profit), leading to fewer shares for future users. If this is not intended by the user, it is merely a mistake! For totalAmountBefore > amount * totalShares, Here is the worst-case scenario (with the minimum amount): first deposit 0.001000 (e4) USDC → 1e12 shares. Second deposit: 0.001 (e4) USDC * 1e12 / 0.001 (e4) USDC. So, the attacker would need to donate 1e16 tokens, meaning 1e10 USDC → 10 billion $. Even in the worst case, it's informational.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!