ERC-4626 virtual-share offset (OZ ≥4.9)
Concrete's assessment for RD-F-074 — scored yellow on the v1.7.0 rubric. The evidence below is the curator's reasoning for this score.
Evidence summary #
Concrete uses a custom conversion library (Conversion.sol) rather than OZ's built-in _decimalsOffset() virtual-share mechanism. The library explicitly implements a +1 virtual offset, documented inline as '// setting uint256 decimalsOffset = 0; // + 10 ** decimalsOffset = 1'. Both calcConvertToShares and calcConvertToAssets add +1 to numerator and denominator. This is equivalent to OZ's _decimalsOffset()=0 (minimal protection). With decimalsOffset=0 the inflation-attack cost scales with only 1 unit of virtual backing — minimal deterrent for empty vaults at launch. OZ 5.2.0 is imported but the _convertToShares/_convertToAssets overrides bypass OZ's built-in virtual shares entirely. Halborn Sep 2025 audit found no finding on this. Yellow: offset present but minimal (0-decimals equivalent); does not meet the 'OZ >=4.9 recommended _decimalsOffset>=6' bar.
Sources #
- GitHubConcrete ConcreteStandardVaultImpl.sol — share conversion overridessrc/implementation/ConcreteStandardVaultImpl.sol — _convertToShares and _convertToAssets override calling Conversion.sol library; Blueprint-Finance/concrete-earn-v2-bug-bountyretrieved 2026-05-17
- Halborn Earn V2 Core audit — Sep 2025Halborn Earn V2 Core — Standard Implementation, Sep 2025: 0 critical/high/medium findings; 3 low, 9 informational — no ERC-4626 share inflation findingretrieved 2026-05-17
- Concrete Conversion.sol — virtual offset implementationsrc/lib/Conversion.sol — calcConvertToShares and calcConvertToAssets with inline comment: '// setting uint256 decimalsOffset = 0; // + 10 ** decimalsOffset = 1'; Blueprint-Finance/concrete-earn-v2-bug-bountyretrieved 2026-05-17
Methodology #
Determine whether ERC-4626 vaults use OpenZeppelin ≥4.9 virtual-share offset pattern to prevent first-depositor share-inflation.
See the full factor methodology and distribution across all protocols →