Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: high
Invalid

Malicious User Can DoS Deposits by Transferring Assets Directly to Vault Contract (ZlpVault.sol)

Summary

The ZlpVault contract enforces a deposit cap using the totalAssets() function within maxDeposit(). However, totalAssets() includes all assets held by the contract, even those sent externally without going through the deposit() function. An attacker can exploit this by artificially inflating totalAssets() via direct asset transfers, reaching the deposit cap and preventing legitimate users from depositing. This results in a Denial-of-Service (DoS) attack on the vault.

Vulnerability Details

  • The problematic logic exists in the maxDeposit() function:

function maxDeposit(address) public view override returns (uint256 maxAssets) {
// load the zlp vault storage pointer
ZlpVaultStorage storage zlpVaultStorage = _getZlpVaultStorage();
// cache the market making engine contract
IMarketMakingEngine marketMakingEngine = IMarketMakingEngine(zlpVaultStorage.marketMakingEngine);
// get the vault's deposit cap
uint128 depositCap = marketMakingEngine.getDepositCap(zlpVaultStorage.vaultId);
// cache total assets held by the vault
uint256 totalAssetsCached = totalAssets();
unchecked {
// Ensures depositCap > totalAssets; otherwise, external deposits can lock out legitimate users
maxAssets = depositCap > totalAssetsCached ? depositCap - totalAssetsCached : 0;
}
}
  • The issue arises because totalAssets() is used to calculate the deposit limit. The function totalAssets() is inherited from ERC4626Upgradeable and is likely implemented as:

function totalAssets() public view virtual override returns (uint256) {
return IERC20(asset()).balanceOf(address(this));
}
  • Since totalAssets() includes all tokens held by the contract, an attacker can artificially inflate this value by sending tokens directly to the vault. When totalAssets() reaches depositCap, maxDeposit() will return 0, blocking all new deposits.

Impact

  • Denial-of-Service (DoS) Attack: Attackers can disrupt normal vault operations by preventing deposits.

  • Liquidity Lock: If deposits are required for further vault operations the protocol’s functionality is severely impacted.

Tools Used

  • Manual

  • ERC4626 Standard Review

Recommendations

  • Instead of relying on totalAssets(), maintain a separate state variable to track deposited funds:

  • Introduce a function to remove externally sent assets and transfer them to the protocol treasury:

  • Instead of outright blocking deposits, allow excess funds but introduce an emergency withdrawal mechanism.

Updates

Lead Judging Commences

inallhonesty Lead Judge
7 months ago
inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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