December 6, 2023

DAO. Solidity

ДАО (англ. DAO — decentralized autonomous organization) — это децентрализованная автономная организация.

Процесс голосования, посредством которого ДАО принимает решения, называется on-chain governance, и он стал центральным компонентом децентрализованных протоколов. ДАО принимает решения, такие как настройка параметров, обновление смарт-контрактов, интеграция с другими протоколами, управление казначейством, выдача грантов и т. д.

Предложение (Propose) - это действие, которое будет исполнено от имени ДАО, если члены ДАО поддержат его.

Стадии через которые проходит предложение от создания до выполнения:

  • После создания предложения оно имеет статус Pending - ожидает начала голосования.
  • После прохождения времени необходимого для ознакомления с предложением, покупки токенов голосования и т.п. начинается период голосования и предложение имеет статус Active.
  • После того как завершился период голосования происходит подсчет голосов. Если набралось достаточное количество голосов и кворум был достигнут, то предложение имеет состояние Succeeded. Если кворум не достигнут и предложение отклонено - Defeated.
  • Далее предложение помещается в очередь на исполнение - Queued.
  • Если предлжение находится слишком долго в очереди, то состояние меняется на Expired.
  • Исполненное предложение имеет стату Executed.
  • Также предложение может быть отменено до исполнения - Canseled.

Пример организации и взаимодействие со смарт-контрактами ДАО

Разберем пример построения ДАО с использованием библиотеки OpenZeppeline v5.0. Нам нужны несколько контрактов для организации ДАО:

Контракты:

TokenGiver - контракт, который будет продавать пользователю токены голосования за USDT.

ERC20Vote - Токен голосования.

Governor DAO - контракт, который отвечает за создание предожений, голосование и планирование исполнения предожений.

TimeLockController - дополнительный контракт, который выполненяет предложение, одобреное контрактом Governor.

Target Contract From Propose - тестовый контракт, за взаимодействие с которым будут голосовать пользователи в нашем тестовом предложении.

Действия:

  1. Proposer создает предложение (состояние предложения Pending)
  2. User приобретает токены голосования (состояние предложения Pending или Active)
  3. User делегирует право голосования (себе или кому то другому) (состояние предложения Pending или Active)
  4. User голосует против, за, или воздержался (состояние предложения Active)
  5. Executer ставит предложение в очередь на исполнение (состояние предложения Succeeded)
  6. Executer запускает исполнение предложение от имени ДАО (состояние предложения Queued или Expired)

Контракт токена для голосования

Создаем контракт, наследуемся от ERC20Votes. Decimals буду использовать равный 6ти, что бы было проще осуществлять обмен с USDT

Создаем контракт для продажи токенов за USDT

Приведу часть контракта собственно DAO. Наследуемся от следующих контрактов:

Governor - основной контракт, для работы с предложениями. Реализует основную логику, которую мы будем дополнять.

GovernorCountingSimple - модуль, реализующий голосование с 3мя вариантами (Против, За, Воздержался)

GovernorVotes - модуль, для расчета веса голоса в зависимости от количества токенов голосования

GovernorVotesQuorumFraction - модуль, отвечающий за кворум

GovernorTimelockControl - модуль, отвечающий за взаимодействие Governor'а и TimeLockController'а

Также приведу часть тестов написанных на Foundry:

Переменные и подготовка контрактов

Тест создающий предложение, голосующий, и исполняющий предложение

Основные моменты про которые нужно помнить

  • После изменения количества токенов голосования нужно вызвать delegate()
  • Для расчета времени используется block.number, а не timestamp
  • Прежде чем исполнить предложение его нужно поместить в очередь на исполнение

Код из статьи можно найти по ссылке

https://github.com/popelev/DAO