Мы часто сталкиваемся с ситуацией, когда клиент хочет объединить доходность из разных DeFi-протоколов, но упирается в зоопарк несовместимых интерфейсов. До появления ERC-4626 каждый yield vault реализовывал собственный интерфейс: Yearn V2 имел pricePerShare(), Compound давал exchangeRate(), Aave работал через aToken с rebasing. Написать агрегатор, который работает с несколькими vault-ами одновременно, означало поддерживать зоопарк адаптеров. ERC-4626 стандартизировал это: один интерфейс для всех токенизированных vault-ов. Сейчас этот стандарт используют Yearn V3, Morpho Blue, большинство liquid staking протоколов и все крупные lending агрегаторы. Это де-факто стандарт для yield-bearing токенов. Если вы разрабатываете DeFi-продукт, закажите разработку vault под ключ — сэкономите время на интеграции и аудите.
Что такое ERC-4626 и почему это важно для интеграций
ERC-4626 — расширение ERC-20 с методами deposit/withdraw активами (underlying asset), mint/redeem shares (vault token), конвертацией между assets и shares. Vault token (shares) — обычный ERC-20, который торгуется и передаётся. Цена share растёт по мере накопления yield. Это фундаментально отличается от rebasing (stETH), где количество токенов меняется, а цена постоянна.
Математика vault: price per share
Цена share в ERC-4626: pricePerShare = totalAssets / totalShares.
| Сценарий | Формула shares | Особенность |
|---|---|---|
| Первый депозит | shares = assets | требуется инициализация виртуальными shares |
| Последующие депозиты | shares = assets * totalShares / totalAssets | округление вниз |
| Снятие | assets = shares * totalAssets / totalShares | округление вверх |
При первом депозите (totalShares = 0) возникает проблема: любая формула с делением на нуль невалидна. OpenZeppelin решает это через virtual shares: инициализируем totalShares = 10^decimals, totalAssets = 10^decimals, что даёт начальный pricePerShare = 1. OpenZeppelin ERC4626 documentation
Инфляционная атака на vault
Это реальная уязвимость, которая позволяет первому depositor-у заработать за счёт последующих. Сценарий: атакующий депонирует 1 wei, получает 1 share, затем donates большой объём актива (минуя deposit), резко повышая pricePerShare. Следующий пользователь депонирует 1000 USDC, но из-за округления вниз получает 0 shares — его активы достаются атакующему.
Как защититься от инфляционной атаки?
OpenZeppelin ERC4626 (v5.0+) защищает через виртуальные shares с _decimalsOffset(). Установка offset=3 создаёт виртуальный запас 10^(3+decimals) shares при 10^decimals assets. Атакующему потребуется депонировать огромную сумму для минимальной выгоды — атака становится экономически невыгодной.
function _decimalsOffset() internal view virtual returns (uint8) {
return 0; // Увеличьте до 3 для дополнительной защиты
}
Реализация базового ERC-4626 vault
Мы используем Foundry, Solidity 0.8.24, OpenZeppelin. Ключевой момент: vault переопределяет totalAssets(), учитывая не только баланс vault, но и активы, задеплоенные в стратегию. Хуки _afterDeposit и _beforeWithdraw управляют деплоем/возвратом средств.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract SimpleYieldVault is ERC4626, Ownable {
address public strategy;
uint256 public performanceFee; // 500 = 5%
constructor(
IERC20 asset_,
string memory name_,
string memory symbol_
) ERC4626(asset_) ERC20(name_, symbol_) Ownable(msg.sender) {}
function totalAssets() public view virtual override returns (uint256) {
uint256 vaultBalance = IERC20(asset()).balanceOf(address(this));
uint256 strategyBalance = strategy != address(0)
? IStrategy(strategy).totalAssets()
: 0;
return vaultBalance + strategyBalance;
}
function _afterDeposit(uint256 assets, uint256) internal virtual {
if (strategy != address(0)) {
IERC20(asset()).approve(strategy, assets);
IStrategy(strategy).invest(assets);
}
}
function _beforeWithdraw(uint256 assets, uint256) internal virtual {
uint256 vaultBalance = IERC20(asset()).balanceOf(address(this));
if (assets > vaultBalance && strategy != address(0)) {
IStrategy(strategy).divest(assets - vaultBalance);
}
}
}
Почему важны направления округления?
ERC-4626 явно специфицирует округление: convertToShares и previewDeposit вниз (floor), previewWithdraw вверх (ceil), previewRedeem вниз. Нарушение — это audit finding. Округление всегда в пользу vault, иначе возможен drain через множество маленьких операций.
Важные edge cases
Если underlying asset — fee-on-transfer токен, vault получает меньше, чем указано. Решение: замерять реальный баланс после transfer и пересчитывать shares. В коде это учитывается.
Сравнение стандартов yield-токенов
| Стандарт | Тип | Удобство интеграции | Риск манипуляций |
|---|---|---|---|
| ERC-4626 | Share-based | Высокое | Низкий (защита от инфляционной атаки) |
| Rebasing | Balance-changing | Среднее | Средний (сложность агрегации) |
| Кастомный | Разный | Низкое | Высокий (нет единого интерфейса) |
ERC-4626 в 2-3 раза лучше для интеграций, чем кастомные или rebasing-решения. Это подтверждается практикой: многие протоколы переходят на этот стандарт, снижая затраты на разработку и аудит.
Тестирование и аудит
Используем официальный набор property tests: ERC4626 Properties. Foundry fuzz-тесты покрывают roundtrip-свойства и инварианты.
function testFuzz_DepositRedeem(uint256 assets) public {
assets = bound(assets, 1, 1e30);
vm.assume(assets <= token.balanceOf(user));
uint256 shares = vault.deposit(assets, user);
uint256 assetsBack = vault.redeem(shares, user, user);
// Потери на округление не более 1 wei
assertApproxEqAbs(assetsBack, assets, 1);
}
Гарантируем прохождение внешнего аудита: контракты проходят Slither, Mythril, Echidna. Получите консультацию по подготовке к аудиту.
Что входит в разработку ERC-4626 vault
- Анализ требований — обсуждаем yield-стратегию, fee-модель, целевую сеть (Ethereum, Polygon, Arbitrum и др.).
- Проектирование архитектуры — схема взаимодействия vault, стратегий, harvester.
- Реализация смарт-контрактов — Solidity 0.8.x, Foundry, OpenZeppelin.
- Тестирование — модульные, fuzz, интеграционные тесты (покрытие >95%).
- Развёртывание и верификация в Etherscan.
- Поддержка при прохождении внешнего аудита — консультации и доработки.
- Техническая документация — описание контрактов, схема вызовов.
За 5 лет работы мы реализовали более 30 DeFi-проектов, включая vault-решения для протоколов с TVL > $100M. Это позволяет нам предвидеть типичные проблемы и давать рекомендации по архитектуре.
Сроки и стоимость
Базовая реализация ERC-4626 vault с одной стратегией: 3-5 рабочих дней. Полноценный vault с harvester, fee-механизмом и несколькими стратегиями: 2-3 недели. Стоимость рассчитывается индивидуально после анализа ваших требований — обычно она ниже, чем разработка с нуля с использованием кастомных интерфейсов.
Свяжитесь с нами для оценки вашего проекта — мы подберём оптимальную архитектуру. Закажите разработку vault под ключ и получите работающий контракт с готовой тестовой базой.
Получите консультацию по вашему проекту — наши инженеры помогут выбрать оптимальную стратегию и снизить риски.







