Incorrect decimalOffset
causes the share-per-asset ratio to be 1
instead of 10^offset
.
The vault's decimals
function returns 18
, while in reality has same decimals as the underlying asset.
When a ZlpVault
is initialized, it sets decimalOffset
. Since the SYSTEM_DECIMALS is 18
, it's safe to assume decimalOffset
will be set to 18 - underlying token decimals
.
ZlpVault
overrides _decimalsOffset(), which is used by the OpenZeppelin (OZ) implementation to calculate the vault's decimals, resulting in 18
.
The ERC-4626 OZ implementation uses decimalOffset
to protect against so-called "inflation attacks."
The protocol overrides _convertToAssets and _convertToShares to implement custom logic.
These functions call getIndexTokenSwapRate
and getVaultAssetSwapRate
, respectively(1, 2). However, the problem is that these functions use a different value for decimalOffset
.
The newly calculated decimalOffset
is 0
, meaning the share-per-asset ratio becomes 1
instead of 10^offset
.
While this still offers protection against inflation attacks (if the offset is 0
, the attacker's loss is at least equal to the users', as noted here), the vault's decimals
function returns 18
, whereas in reality, it matches the underlying asset's decimals.
Smaller protection against inflation attack for vaults with assets with less than 18 decimals;
Vault decimals misrepresentation. It could represent an external risk in case of vault's integration with other protocols.
Ensure consistency in how decimalOffset
is used acros functions.
Modify getIndexTokenSwapRate
and getVaultAssetSwapRate
to correctly derive decimalOffset
from the underlying token, or better, read it directly from zlpVault.
Consider setting zlpVaultStorage.decimalsOffset
to SYSTEM_DECIMALS - underlyingAssetDecimals
.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.