← thrum blog post / ERC-4626

ERC-4626 Manipulation Detector (4626-INFLATION-SCAN)

This detector module implements an ERC-4626-aware detector for tracking donation, inflation, and exchange-rate manipulation risks associated with vaults that follow the ERC-4626 standard. It aims to go beyond naive pattern checks by doing the following:

  • classifying ERC-4626-like vaults
  • analyzing donation sensitivity of totalAssets()
  • approximating whether the vault is empty-reachable
  • detecting pro-rata share minting patterns
  • spotting internal accounting and mitigation attempts in totalAssets()

The goal is to identify vaults that are structurally exposed to donation-based exchange-rate attacks (as seen in various recent multi-million-dollar DeFi incidents).

An intro to ERC-4626 vaults

An ERC-4626 vault exposes

  • an underlying asset asset()
  • a notion of total managed assets totalAssets(), and
  • share-to-asset conversion functions like convertToShares, convertToAssets, and mint/withdraw/redeem/deposit.

Donation and inflation attacks usually share a common pattern:

  1. Vault's totalAssets() is essentially asset.balanceOf(address(this)).
  2. Shares mint proportional via assets * totalSupply / totalAssets.
  3. Vault can be brought close to empty by normal users.
  4. An attacker donates assets directly to the vault or manipulates the asset balance, skewing the share price.
  5. Subsequent deposits/withdrawals/externals that trust the vault's price can be exploited.

This encodes that structure as explicit boolean predicates and uses them to produce a severity estimate that is useful in stopping million-dollar bugs before they go live.

Note: This bug pattern has absolutely (a) no public paper, (b) no formal implementation, (c) no formal specification, and (d) only has hand-wavey "mitigations" that aim to stop bugs associated with ERC-4626 before they go live -- these are shipped by OZ and others. Thrum's detector attempts to formally detect any such patterns seen in the wild along with some generalizations and good practices. In other words: we're the only detector company shipping this.

Getting started

When you call thrum scan ., you will trigger our entire suite of detectors in the cloud. One such detector will be 4626-INFLATION-SCAN.

The output structure will be in the form of A or B -- A if you have no findings, B if you have some findings:

# A
[ERC-4626] No risks found for ERC-4626 in `your-contract-repo-here`

# B
[2 ERC-4626 risks found in `your-contract-repo-here`]
[A1]
[ERC4626 Inflation] `Naive4626Vault` looks like an ERC-4626 vault (`kind=abi_strict`,
empty_reachable=True, rounding_share_mint=True, internal_accounting=False) and uses
raw balanceOf(this) in `totalAssets()`, making it sensitive to donations.
Missing core ERC-4626 funcs: none. Inferred severity: high.
    -> contracts/Naive4626Vault.sol:10-210
[MITIGATIONS]
    - In `totalAssets()`, avoid using raw assetToken.balanceOf(address(this)).
    Instead, track assets via an internal accounting variable that is only
    updated in deposit/mint/withdraw/redeem, or subtract known external
    balances from the raw token balance.
    - Seed the vault with an initial permanent position (e.g., protocol-owned
    liquidity) so that small donations cannot significantly move the
    exchange rate.
    - Use a `mulDiv` or equivalent helper that clamps extreme ratios and
    consider imposing caps on previewDeposit/previewMint slippage.

    - Avoid using this vault’s convertToAssets/totalAssets as a direct price
    oracle for lending/borrowing without additional sanity checks.
    - If this vault is integrated into another protocol, enforce maximum
    deviation of asset/share price from a reference oracle over a single
    transaction or block.

    Run `thrum produce A1` to generate an exploit from your vulnerability.

    Add a test that performs the classic donation attack:
        1) User deposits assets when vault is empty.
        2) Attacker donates a large amount of assets directly.
        3) Attacker calls deposit/mint again and confirms that they receive
        disproportionately cheap shares.
    Verify that after your fixes, the above scenario no longer produces
    outsized profit for the attacker.
[A2] ...

How it works (high-level)

Thrum's ERC-4626 detector runs a multi-stage analysis combining:

  1. Vault discovery. Identify contracts behaving like ERC-4626 vaults, even if they don't inherit a library or follow textbook interfaces. This catches partial compliance that simple checks miss.
  2. Structure and flow analysis. Once candidates are tractable, inspect how assets and shares move. We track things like how totalAssets() is computed, how deposits and withdrawals are priced, and how the vault behaves in edge states (e.g. "nearly empty," "heavily skewed").
  3. Risk scoring. The detector folds signals for our LLM pipeline. All important verified bugs and mitigation steps are returned.

The detector answers this question with near-perfect precision:

Is this ERC-4626-style vault exposed to donation-driven or exchange-rate-manipulation risk?

It is great at highlighting:

  • vaults whose accounting makes them sensitive to external donations or manipulations of the underlying asset balance.
  • implementations that are dangerous when the vault can be emptied by unprivileged users.
  • scenarios where share/asset pricing logic makes it easy to buy shares cheaply or expensively after manipulation.
  • vaults whose design suggests they attempt mitigations so auditors know to scrutinize those paths more closely.

It is not great at highlighting:

  • formal safety proofs in the ERC-4626 class.
  • a verifiable full-audit.
  • every bug in this class as it is still being built -- the goal is to hit near-perfect accuracy on this closed bug class.

Practicing responsible detection

New bug class detection is useful if and only if we responsibly deploy our detectors. Thrum follows the golden rules of crypto security:

  1. We shouldn't aim to introduce a new class of detectors for bugs that don't exist meaningfully in practice yet.
  2. We shouldn't aim to solve a class of bugs that is deemed unsolvable.
  3. We shall never claim perfect accuracy on a toolset that has historically been emergent in detection capabilities.

Roadmap

4626-INFLATION-SCAN is the first step in a broader family of vault and yield-strategy detectors. We plan to:

  • Link 4626 vault findings to downstream consumers to highlight where price manipulation could cascade into liquidations or bad debt.
  • Integrate with thrum produce so that a finding can be paired with a generated fuzz or PoC demonstrating real financial impact under reasonable conditions.
  • Extend structural reasoning to non-4626 vault patterns.
  • Allow teams to tune enforcement levels; currently we trauma dump every nitpick in your software.

To get involved, link your Wallet. You may also consider participating in the Beta program.

security / research inquiries → vlad@usatii.com