Skip to content
Last updated: February 06, 2026

SCWE-135: ERC4626 Share Inflation via Donations

Stable Version v1.0

This content is in the version-(v1.0) and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).

Send Feedback

Relationships

Description

ERC4626 vaults that do not guard against free-asset donations can skew totalAssets and share price. Attackers can donate assets to inflate share value and then mint shares cheaply before normalization, extracting value from existing holders.

Remediation

  • Normalize share price on every deposit/mint using current totalAssets.
  • Optionally block unsolicited donations by reverting on direct transfers or sweeping them into reserves before new share mints.
  • Add tests for donation and price-per-share edge cases.

Examples

Vulnerable

// totalAssets() uses balanceOf; donations inflate it and skew share price
function mint(uint256 shares) external {
    uint256 assets = previewMint(shares);
    asset.transferFrom(msg.sender, address(this), assets);
    _mint(msg.sender, shares);
}

Fixed

uint256 private _accountedAssets; // internal balance; excludes direct transfers

function totalAssets() public view override returns (uint256) {
    return _accountedAssets; // donations do not affect share price
}

function deposit(uint256 assets, address receiver) public override returns (uint256 shares) {
    uint256 before = asset.balanceOf(address(this));
    shares = super.deposit(assets, receiver);
    _accountedAssets += (asset.balanceOf(address(this)) - before);
}

function withdraw(uint256 assets, address receiver, address owner) public override returns (uint256 shares) {
    shares = super.withdraw(assets, receiver, owner);
    _accountedAssets -= assets;
}