Final ERC standard for tokenized yield-bearing vaults built on a single ERC-20 underlying asset. Standardizes deposit/mint/withdraw/redeem semantics and share-to-asset conversion previews.
- 01yield aggregators
- 02lending market share tokens
- 03staking wrappers
- 04vault composability
- 05accounting standardization
- pnpm add @openzeppelin/contracts
- forge install transmissions11/solmate
- forge install vectorized/solady
Implement vaults against the IERC4626 interface and inherit OpenZeppelin's ERC4626 (which extends ERC20). Expose `deposit(assets, receiver)`, `mint(shares, receiver)`, `withdraw(assets, receiver, owner)`, `redeem(shares, receiver, owner)` and the matching `previewDeposit/previewMint/previewWithdraw/previewRedeem` rounding helpers. Always emit `Deposit` and `Withdraw` events and expose `asset()`, `totalAssets()`, `convertToShares()`, `convertToAssets()`. Round in favor of the vault on deposit/withdraw and round in favor of the user on mint/redeem to match the spec. For new vaults, mitigate the first-deposit inflation attack via OpenZeppelin's `_decimalsOffset()` virtual-shares pattern or a dead-shares initial deposit.
- ⚑First-deposit inflation attack: an attacker mints 1 share then donates assets to inflate the price-per-share, stealing from later depositors — mitigate via virtual shares (OpenZeppelin `_decimalsOffset`), an initial dead-shares mint to address(0xdead), or seeded liquidity at deployment.
- ⚑`previewDeposit/previewMint/previewWithdraw/previewRedeem` must MUST NOT account for vault-specific limits (slippage, fees not present at preview time) — they should match the actual call result on-chain at the same block.
- ⚑Rounding direction matters: deposit/mint should round shares down for the user, withdraw/redeem should round assets down for the user; flipping rounding leaks value from the vault.
- ⚑`maxDeposit`/`maxMint`/`maxWithdraw`/`maxRedeem` must reflect real on-chain limits (paused vaults, supply caps, available liquidity) — integrators rely on these for routing.
- ⚑Inheriting ERC-4626 without overriding `_convertToShares`/`_convertToAssets` for fee-on-transfer or rebasing underlyings will silently break accounting.