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.