|
| 1 | +# Vault |
| 2 | + |
| 3 | +Волты (vaults) предоставляют возможность пользователям передавать свои активы в управление и получать от этого доход (yield). Это упрощает процесс формирования портфеля: пользователю не нужно изучать большое количество протоколов и разбираться в способах получения максимальной доходности. Разработчики автоматизировали все необходимые действия внутри стратегии волта, что значительно облегчает использование. |
| 4 | + |
| 5 | +## TЗ |
| 6 | + |
| 7 | +Необходимо написать два основных смарт-контракта, которые реализуют функционал волта: |
| 8 | + |
| 9 | +- Vault – смарт-контракт, с которым взаимодействует конечный пользователь. Расширяет ERC20 и является share-токеном; |
| 10 | +- Strategy – смарт-контракт, предназначенный для управления want-токенами. |
| 11 | + |
| 12 | +### Расшифровка некоторых понятий |
| 13 | + |
| 14 | +- **want-токен** (underlying токен) – токен, которым управляет волт. Это может быть любой ERC20 токен; |
| 15 | +- **share-токен** – токенизированная доля пользователя в волте в формате ERC20; |
| 16 | +- **yield** – доход пользователя. |
| 17 | + |
| 18 | +### Как это выглядит для конечного пользователя |
| 19 | + |
| 20 | +У пользователя есть определенное количество want-токенов. Управление этим активом самостоятельно может быть сложным, поэтому проще найти платформу, которая принимает данный актив в управление. |
| 21 | + |
| 22 | +Пользователь находит такую платформу, видит список волтов и их доходность. Он выбирает волт, работающий с его want-токенами, и делает депозит, физически передавая want-токены в управление волту. Взамен он получает share-токены. |
| 23 | + |
| 24 | +Затем пользователь наблюдает за ростом баланса, доступного для вывода из волта. В любой момент он может передать свои share-токены обратно волту и получить то, что вложил, плюс накопленный доход (yield), если стратегия была успешной. |
| 25 | + |
| 26 | +### Как это выглядит со стороны смарт-контрактов (core-функционал) |
| 27 | + |
| 28 | +Работу волта обеспечивают два основных контракта – Vault и Strategy. |
| 29 | + |
| 30 | +Примерный воркфлоу работы волта: |
| 31 | + |
| 32 | +1. Пользователи делают депозит в волт, на контракте волта накапливаются want-токены. |
| 33 | +2. Стратегия забирает накопившиеся want-токены и использует их для получения дохода. |
| 34 | +3. Через определенные промежутки времени бот активирует стратегию, чтобы она снова забрала все пользовательские депозиты из волта и отчиталась о текущих заработках или потерях. |
| 35 | +4. Время от времени пользователи могут выходить из волта. В таком случае сначала используются свободные средства на волте; если их недостаточно, волт запрашивает недостающую сумму у стратегии. |
| 36 | + |
| 37 | +### Ответственность волта |
| 38 | + |
| 39 | +- Принимать от пользователей want-токены и выпускать взамен share-токены; |
| 40 | +- Принимать и сжигать share-токены, возвращая пользователям соответствующее количество want-токенов; |
| 41 | +- Вести учет количества want-токенов, переданных в стратегию; |
| 42 | +- Переводить performance и management fees (комиссию) на адрес feeRecipient: |
| 43 | + - managementFee - это плата за использования протокола, она исчисляется в процентах годовых (например 1%) и списывается со всего депозита который обслуживает стратегия, списывается только в случае если стратегия в плюсе; |
| 44 | + - performanceFee - это комиссия только с доходов стратегии, а не со всего депозита, также списывается только когда стратегия что-то заработала. |
| 45 | + Пример: |
| 46 | + Стратегия управляет `1000$`. До вызова `harvest()` стратегия заработала `100$`, общее количество средств `1100$`. Предположим managementFee = 1%, performanceFee = 0.5%, тогда: |
| 47 | + - managementFee = 1100 * 1% / 12 = `0.92$` |
| 48 | + - performanceFee = 100 * 0.5% = `0.5%` |
| 49 | + Общая комиссия: 0.92 + 0.5 = `1.42$`. Если общая комиссия превышает доход - приравниваем ее к полученному доходу (стратегия не должна уйти в минус). |
| 50 | + |
| 51 | +**Формула для депозита:** |
| 52 | + |
| 53 | + |
| 54 | + |
| 55 | +- *tA* – Vault.totalAssets (want-токен) |
| 56 | +- *tS* – Vault.totalSupply (share-токен) |
| 57 | +- *dA* – depositAmount (сумма депозита) |
| 58 | +- *s* – shares to mint (количество share-токенов для выпуска) |
| 59 | + |
| 60 | +### Ответственность стратегии |
| 61 | + |
| 62 | +- Взять want-токены из волта и использовать их в соответствии с принятой стратегией управления; |
| 63 | +- Синхронизировать доходы и убытки с волтом. |
| 64 | + |
| 65 | + |
| 66 | +### Дополнительный функционал (обязательный) |
| 67 | + |
| 68 | +- Возможность приостановки работы стратегии с возвратом всех want-токенов на баланс стратегии; |
| 69 | +- Возможность экстренной остановки стратегии в случае взлома или подозрения на взлом. Необходимо максимально вернуть want-токены и перевести их на адрес владельца; |
| 70 | +- Возможность миграции на новую стратегию. Старая стратегия должна быть опустошена и остановлена; |
| 71 | +- Поддержка нескольких стратегий одним волтом. |
| 72 | + |
| 73 | +### Внешние сервисы |
| 74 | + |
| 75 | +- Настроить сервис для создания бота, который будет вызывать методы стратегии по определенным триггерам; |
| 76 | +- Написать и задеплоить сабграф, который будет отображать текущее состояние стратегии на момент последней транзакции. |
| 77 | + |
| 78 | +## Пример простой стратегии |
| 79 | + |
| 80 | +Необходимо найти DeFi-протокол, который поощряет провайдеров ликвидности дополнительными вознаграждениями. Условия получения вознаграждений могут варьироваться: в некоторых протоколах потребуется застейкать LP-токен (токен, полученный от депозита в пул ликвидности). |
| 81 | + |
| 82 | +Алгоритм работы стратегии может выглядеть следующим образом: |
| 83 | +1. Стратегия вкладывает want-токены в пул ликвидности DeFi-протокола и получает LP-токен пула. |
| 84 | +2. DeFi-протокол распределяет по пулу свои комиссии (т.е. стоимость LP-токена, которым владеет стратегия, растет) и начисляет вознаграждения. |
| 85 | +3. Раз в сутки стратегия конвертирует вознаграждения в want-токены с помощью Uniswap и повторяет первый шаг. |
| 86 | + |
| 87 | +## Требования к выполнению задания |
| 88 | + |
| 89 | +- **Соблюдение лучших практик**. Код должен быть структурированным, читабельным, соответствовать базовым правилам безопасности. |
| 90 | +- **Проверка кода с помощью Slither**. Допустимы только некоторые низкоприоритетные предупреждения, не представляющие угрозу безопасности. |
| 91 | +- **Функции должны эмитить соответствующие события на изменение состояния смарт-контракта**. События должны содержать только важные данные, которые будут использоваться снаружи. |
| 92 | +- **Необходимые проверки входных данных**. Например, проверка на нулевой адрес для токенов оплаты ERC-20, чтобы избежать ошибок или потерь средств. |
| 93 | +- **Ограничение доступа к функциям смарт-контракта**. Использовать расширения Ownable или AccessControl для ограничения доступа к важным функциям протокола. |
| 94 | +- **Во время проектирования архитектуры думайте об основных инвариантах протокола**. Инвариант — это свойство системы, которое никогда не должно нарушаться, например, сумма балансов всех держателей токенов должна соответствовать общему предложению токенов или количество токенов для перевода должно соответствовать фактически полученному количеству смарт-контрактом. Рекомендуется ознакомиться с подходами CEI (Checks-Effects-Interactions) и FREI-PI (Function Requirements-Effects-Interactions + Protocol Invariants). |
| 95 | +- **Использование ReentrancyGuard от OpenZeppelin** для защиты функций смарт-контракта от повторных вызовов (где это необходимо). |
| 96 | +- **Использовать стандарт ERC-4626**. |
| 97 | +- **Проект должен быть разработан с использованием [Foundry](https://github.com/foundry-rs/foundry)**. Без использования Hardhat. |
| 98 | +- **Должны быть написаны деплой-скрипты**. В формате ContractName.s.sol. |
| 99 | +- **Покрытие юнит-тестами должно быть 100%**. Проверка должна выполняться через команду `forge test --coverage`. |
| 100 | +- **Написание интеграционных тестов на форке мейннета**. Тесты должны подтвердить, что протокол может взаимодействовать с Uniswap и выбранным DeFi-протоколом для стратегии. Например, можно использовать версии Uniswap, начиная с v2, и DeFi-протоколы типа Compound v2. |
| 101 | +- **Деплой смарт-контрактов в тестнет**. Смарт-контракты волта и стратегии должны быть верифицированы. |
| 102 | +- **Рабочий сабграф**. Сабграф должен функционировать без ошибок и содержать основные сущности с данными. Необходимо подумать, какие данные могут понадобиться вашему web3-приложению на клиенте. Рекомендуется использовать сервисы с playground для API, такие как The Graph. |
| 103 | +- **Документация**. Подробное описание по развертыванию, запуску проекта и по функционалу смарт-контрактов. |
| 104 | +- **Видео-демонстрация работы сервиса**. Необходимо записать видео расшаренного экрана с демонстрацией работы сервиса, для ускорения ревью. |
| 105 | +- **Репозиторий github**. Оформленный и задокументированный код необходимо предоставить для ревью в виде ссылки на репозиторий. |
| 106 | + |
| 107 | +## Полезные ссылки |
| 108 | + |
| 109 | +- Code: Волт от [Yearn](https://github.com/yearn/yearn-vaults/blob/main/contracts/Vault.vy). Для вдохновения. Написан на vyper, но его довольно легко понять |
| 110 | +- Standard: [ERC-4626: Tokenized Vaults](https://eips.ethereum.org/EIPS/eip-4626) |
| 111 | +- Article: [ERC-4626 Interface Explained](https://www.rareskills.io/post/erc4626) |
0 commit comments