The virtual offset is used to prevent inflation attack. Zlpvault has a custom offset within their contract. The implementation between Zlpvault and the VaultRouterBranch is inconsistent which can cause users to redeem lesser asset tokens.
When calling VaultRouterBranch::redeem
, a specified amount of index tokens is exchanged for collateral assets from the given vault. The calculation of the exchanged tokens can be influenced (inflated) if the decimalOffset
differs. When determining the swap rates using previewAssetsOut
and previewSharesOut
, the decimalOffset
is factored into the calculations using the IERC20
interface.
For example, if the initialized decimalOffset
is greater than 0—as in the case of ZlpVault
, where is can be initizlied to any number [9 is the safest](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3979)—the ERC4626Upgradable::decimals
method incorporates this offset using _underlyingDecimals + _decimalsOffset()
. Consequently, when users call VaultRouterBranch::redeem
, the assets and shares they receive are reduced due to the initialized decimalOffset
in ZlpVault
. This discrepancy in decimal offset precision is significant because users depositing tokens will consistently receive fewer tokens upon redemption.
Within the VaultRouterBranch.sol
:
Within Zlpvault.sol
:
Within the ERC4626Upgradable.sol
:
User redeems lesser assets tokens leading to a loss.
Manual Review
Change the implementation uint8 decimalOffset = Constants.SYSTEM_DECIMALS - IERC20Metadata(vault.indexToken).decimals()
into Zlpvault's uint8 decimalOffset = ZLPVAULT.decimals() - IERC20Metadata(vault.indexToken).decimals()
. This ensures that the decimalOffset
is consistent through out Market Engine and vaults.
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.