Розробка платформи крипто-сбережень
Користувач хоче покласти USDC і отримувати проценти, не розбиралося в тому, як працює Aave або Compound. Це задача агрегації yield-стратегій за простим інтерфейсом. Складність — не в UI, а в тому, що під капотом потрібно правильно управляти ліквідністю, не потерять пользовательские кошти при перемиканні стратегій і коректно розраховувати проценти без накопичувальних помилок округлення.
Начисление процентов: де теряються кошти користувачів
Continuous compounding vs discrete accrual
Aave V3 використовує liquidityIndex — накопичувальний множник, який росте безперервно. Баланс користувача — це scaledBalance * currentLiquidityIndex. При будь-якій дії (deposit, withdraw) scaledBalance перераховується через поточний індекс.
Власна реалізація начисления процентів, яку нам принесли на ревью, рахувала проценти інакше: balance += balance * rate * blocks_elapsed / YEAR_IN_BLOCKS. Здавалось, еквівалентно. Проблема виникла при депозитах: якщо користувач довносив кошти, старий баланс перахувався по новій ставці, а не по ставці на момент першого депозиту. За 6 місяців накопилась помилка ~0.3% — невелика в процентах, але значима при TVL $5M.
Правильний підхід: зберігати scaledBalance і глобальний growthIndex. Всі операції — через індекс. Це стандарт ERC-4626, який саме для цього й створювався.
ERC-4626 як основа
ERC-4626 (Tokenized Vault Standard) вирішує задачу крипто-сбережень елегантно: користувач вносить assets (USDC), отримує shares (sUSDC). convertToAssets(shares) завжди повертає поточну вартість з урахуванням накопленого yield. Не потрібно придумувати своє.
Критичний момент: функція previewRedeem повинна повертати точно те кількість assets, яке отримає користувач при redeem. Розбіжність між preview та actual — порушення стандарту й потенціальний front-running вектор. EIP-4626 спеціально вимагає previewRedeem бути pessimistic (округлення вниз для користувача), щоб протокол ніколи не йшов в борг.
Стратегії yield — агрегація і ребалансування
Інтеграція з Aave V3
Aave Pool контракт приймає supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode). В відповідь користувач отримує aToken (aUSDC), що автоматично начисляє проценти через збільшення liquidityIndex. При withdraw — withdraw(asset, amount, to).
Для платформи сбережень vault контракт виступає onBehalfOf — тримає всі aTokens у себе, видає shares користувачам.
Ребалансування між протоколами
Якщо yield на Compound вищий Aave — протокол повинен перевести ліквідність. Це звучить просто, але є нюанси:
- Withdraw з Aave може займати час якщо utilization rate високий (немає вільної ліквідності)
- Gas на ребалансування з'їдає частину yield для дрібних депозитів
- Flash ребалансування через flash loan — можна переместити весь депозит атомарно: взяти flash loan USDC → supply в новий протокол → withdraw з старого → повернути flash loan. Платиш 0.09% flash loan fee замість двох окремих транзакцій.
Поріг ребалансування: різниця yield повинна покривати gas + flash loan fee з запасом. Інакше ребалансування збитковим. Типовий поріг — 0.5-1% років різниця.
Chainlink для розрахунків цін
При мультивалютних сбережнях (депозит ETH, yield в USDC) потрібні price feeds для коректного відображення баланса в базовій валюті. Chainlink Data Feeds на Ethereum mainnet та L2 — стандарт. Важливо: перевіряти updatedAt timestamp feed, щоб не використовувати stale price. Якщо block.timestamp - updatedAt > heartbeat * 2 — ціна застаріла, потрібен fallback.
Гнучкі умови: fixed vs flexible terms
Flexible deposits (як у звичайному сберегальному рахунку): вивід в будь-який момент, ставка змінна. ERC-4626 vault — стандартна реалізація.
Fixed-term deposits (як депозит в банку): користувач блокує кошти на 30/90/180 днів, отримує більш високу ставку. Реалізація: lockedUntil timestamp в маппінгу, withdraw перевіряє його. Ставка — фіксується при депозиті через snapshot yieldIndex.
Проблема з fixed-term: якщо потрібна liquidity до терміну, користувач втрачає накопленю yield та/або платить penalty. Це потрібно явно обозначити в UI та смарт-контракте — earlyWithdrawPenalty в базисних пунктах.
Безопасність
Rug pull защита: admin не повинен мати можливість вивести користувальські кошти довільно. onlyOwner на withdraw — червоний прапор для аудиторів. Timelock на зміну стратегій (мінімум 24-48 годин) через Gnosis Safe + TimelockController.
Паузуємість: при виявленні проблеми з протоколом, в який інвестовані кошти (Aave exploit) — потрібна швидка пауза на нові депозити. Pausable від OpenZeppelin + Emergency withdrawal режим, який дозволяє користувачам вивести кошти навіть в паузі (тільки виводи, ніяких нових депозитів).
Максимальний депозит per user: захист від концентрації ризику й whale domination, яка заважає іншим користувачам виводити кошти.
Процес роботи
Аналітика (2-3 дні). Вибір базових протоколів, tokenomics (є ли reward token платформи), multi-chain або single chain, вимоги до KYC/compliance.
Розробка (1-2 тижні). ERC-4626 vault → інтеграція стратегії → ребалансер → timelock + governance.
Тестування. Fork-тести на Ethereum mainnet: реальні ставки Aave, реальний USDC. Сценарії: депозит → yield → ребалансування → вивід. Fuzz на deposit/withdraw/redeem з випадковими сумами й часовими параметрами.
Орієнтири по термінам
Простий vault на базі одного протоколу (Aave) з ERC-4626 — 1 тиждень. Мультистратегійна платформа з ребалансуванням, fixed-term депозитами та governance — 4-6 тижнів.
Вартість рахується індивідуально.







