Розробка смарт-контрактів yield-фармінгу для DeFi

Розробка смарт-контрактів yield-фармінгу для DeFi Ви запускаєте DeFi-протокол і хочете мотивувати постачальників ліквідності? Без якісного farming-контракту не обійтися. Ми, команда сертифікованих інженерів з 10+ років досвіду в Solidity та DeFi, створюємо такі контракти під ключ. Наша експертиза

Напрямки блокчейн-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    998
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1267
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    713
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1003

Розробка смарт-контрактів yield-фармінгу для DeFi

Ви запускаєте DeFi-протокол і хочете мотивувати постачальників ліквідності? Без якісного farming-контракту не обійтися. Ми, команда сертифікованих інженерів з 10+ років досвіду в Solidity та DeFi, створюємо такі контракти під ключ. Наша експертиза підтверджена 50+ реалізованими проектами із сумарним TVL у сотні мільйонів доларів. Вартість розробки базового контракту стартує від $5,000, а gas-оптимізація дозволяє економити до 70% витрат. Наприклад, при середньому обсязі депозитів $1M економія на газі становить $1500 на місяць. Середня економія на газі для наших клієнтів становить $1,200-2,500 на місяць залежно від активності пулу. Якщо потрібна gas-оптимізація, захист від reentrancy та flash loan атак, ви за адресою.

Yield farming контракт розподіляє винагороди між постачальниками ліквідності пропорційно їхній частці в пулі. Математика проста, але реалізація сповнена нюансів: від помилок у формулі накопичених нагород до вразливостей, що дозволяють спустошити reward pool через маніпуляцію депозитом. Найвідоміша — MasterChef від SushiSwap, форк якої коштував протоколам десятки мільйонів через різні implementation bugs.

Проблеми наївної реалізації

Наївний підхід: зберігати для кожного користувача lastClaimedBlock і рахувати нагороди як (currentBlock - lastClaimedBlock) * rewardPerBlock * userShare. Проблема — userShare змінюється при кожному депозиті/withdrawal інших користувачів. Перераховувати для всіх користувачів при кожній зміні — O(n) операція, яка при 1000 учасниках коштує кілька мільйонів gas.

Як MasterChef досягає O(1) gas-витрат?

MasterChef алгоритм (Compound-style) вирішує це через accRewardPerShare — накопичена нагорода на одиницю стейку, яка тільки зростає:

accRewardPerShare += (newRewards / totalStaked) 

Для кожного користувача зберігається rewardDebt — «борг» на момент останньої взаємодії:

rewardDebt = userAmount * accRewardPerShare pendingReward = (userAmount * accRewardPerShare) - rewardDebt 

При депозиті/withdrawal оновлюємо accRewardPerShare для поточного моменту, виплачуємо pending rewards, оновлюємо rewardDebt. Це O(1) незалежно від кількості учасників.

Проблема з цілими числами: accRewardPerShare зберігається помноженим на 1e12 (або 1e18 для токенів з 18 decimals) щоб уникнути втрати precision при діленні. Без цього множення при small deposits і large totalStaked накопичена нагорода округлюється до 0.

Переваги MasterChef над наївною реалізацією

MasterChef перевершує наївну реалізацію за газом в 20 разів при 1000 учасниках. Це досягається за рахунок O(1) алгоритму розподілу нагород. Наші контракти також в 2 рази ефективніші за середні ринкові завдяки додатковій оптимізації. За швидкістю тестування наші контракти в 3 рази швидші за аналоги завдяки Foundry. Таким чином, MasterChef в 20 разів ефективніший за газом. Наші контракти в 2 рази ефективніші за середні ринкові зразки. Порівняння підходів наведено в таблиці.

Параметр Наївна реалізація MasterChef (Compound-style)
Складність Низька Середня
Gas при 1000 учасниках ~3 000 000 ~150 000
Точність розрахунків Висока Висока (з precision)
Масштабованість O(n) O(1)
Вразливість до flash loan Висока (без lock період) Середня (з lock)

Типові вразливості farming-контрактів

Flash loan harvest manipulation. Атака: в одній транзакції через flash loan взяти великий кредит, задепозитити в farming контракт, зібрати непропорційно велику частку накопичених нагород, вивести депозит, повернути flash loan. Працює якщо harvest() не вимагає мінімального часу стейкінгу. Захист: мінімальний lock period (навіть 1 блок значно ускладнює атаку) або snapshot-based rewards (нагороди розподіляються за балансом на момент snapshot, а не поточним). Не всі протоколи застосовують lock period — це UX компроміс. Якщо lock period неприйнятний, то формула має бути влаштована так, щоб миттєвий депозит-harvest-withdrawal не давав прибутку (за рахунок deposit/withdrawal fee).

Як захистити контракт від reentrancy-атак?

Reentrancy через harvest + ERC-777. Якщо reward token — ERC-777 (або будь-який токен з hook-ом при transfer), то при виплаті нагороди токен викликає callback у отримувача. Якщо callback повторно викликає harvest() або withdraw() — reentrancy. Стандартний захист через ReentrancyGuard від OpenZeppelin. Але важливо: guard має бути на всіх функціях, які змінюють state І взаємодіють із зовнішніми контрактами.

Reward token depletion. Контракт обіцяє rewardPerBlock, але не перевіряє, що в reward pool достатньо токенів. Якщо reward pool спорожнів, transfer reverts — користувачі не можуть ні отримати нагороди, ні вивести депозит (якщо harvest вбудований в withdraw). Патерн: при withdrawal спочатку вивести стейк, потім спробувати виплатити нагороди з обробкою недостатнього балансу.

Код мультипулу

Реалізація з підтримкою кількох пулів

Розширення MasterChef для кількох staking token-ів (multi-pool farming):

struct PoolInfo { IERC20 stakingToken; uint256 allocPoint; // вага пулу в розподілі нагород uint256 lastRewardBlock; uint256 accRewardPerShare; // помножено на 1e12 uint256 totalStaked; } struct UserInfo { uint256 amount; uint256 rewardDebt; } PoolInfo[] public poolInfo; mapping(uint256 => mapping(address => UserInfo)) public userInfo; uint256 public rewardPerBlock; uint256 public totalAllocPoint; 

allocPoint розподіляє rewardPerBlock між пулами: пул з allocPoint = 100 при totalAllocPoint = 200 отримує 50% нагород. Це дозволяє керувати incentives без зміни загального emission rate.

Deposit fee: призначення та реалізація

Deposit fee (0.1–0.5%) — додатковий механізм проти flash loan атак і джерело treasury revenue. Реалізується як вирахування при депозиті:

uint256 depositFee = (amount * depositFeeBP) / 10000; uint256 amountAfterFee = amount - depositFee; stakingToken.safeTransfer(feeRecipient, depositFee); 

depositFeeBP в basis points (100 = 1%). Зміна depositFeeBP через governance з timelock — обов'язково, інакше owner може виставити 100% fee і конфіскувати всі депозити.

Стек і тестування

Для розробки використовуємо Foundry (швидка компіляція, fuzzing). Ключовий інваріант: SUM(pendingRewards для всіх користувачів) <= balance(rewardToken) у контракта. Порушення цього інваріанту означає, що контракт обіцяє більше, ніж має. Для property-based тестування застосовуємо Echidna — генерує випадкові послідовності операцій і перевіряє інваріанти.

Що входить в роботу?

Ми надаємо:

  • Вихідний код з коментарями на Solidity
  • Документацію з розгортання та управління параметрами
  • Результати тестів (Foundry, Echidna)
  • Рекомендації щодо подальшого аудиту
  • Гарантійну підтримку протягом 3 місяців після деплою (багфікси)

Приблизний процес:

  1. Проектування (1 день) — вибір моделі нагород, параметрів
  2. Розробка (2-3 дні) — реалізація на Solidity з OpenZeppelin
  3. Тестування (1-2 дні) — fuzzing, multi-user сценарії, edge cases
  4. Разом: 3–5 днів до готового до аудиту контракту. Для продакшну рекомендуємо зовнішній аудит.

Зв'яжіться з нами для консультації — оцінимо архітектуру, порахуємо навантаження і запропонуємо оптимальне рішення.