Привет! Для меня некоторое время было удивительно, почему некоторые проекты стали выбирать ERC-721 протокол для выплаты дивидендов, неужели это дань моде? Но поразмыслив немного, я, кажется, пришел к пониманию в чем преимущества этого подхода.

В этой статье не будет деталей о самих протоколах, но все же для контекста, расскажу пару слов о базовых понятиях, которые мы будем использовать. Дивиденды — выплаты процента от дохода совладельцам бизнеса. ERC-20 протокол устанавливает факт владения N единицами чего-то, но единицы эти обезличенные. ERC-721 протокол устанавливает факт владения некоторой идентифицируемой сущностью.

Итак, на заре EVM люди участвовали в ICO, и в результате им выдавали ERC-20 токены выбранного ими проекта, условно говоря, мне сказали, у тебя есть 30л воды. Далее, у токена может быть область применения, скажем, оплата транзакций в сети, места под контракт и тому подобное. В результате, я, как счастливый обладатель токенов либо могу пользоваться этими благами сам, либо продать тем, кому они нужны.

Но не все токены имеют область применения. Некоторые, созданы исключительно для определения доли участия в проекте, и, как следствие, в распределении наград. Такие токены очень похожи на акции компаний, выплачивающих дивиденды. И даже процесс происходит схоже: в обговоренную дату происходит так называемая дивидендная отсечка, или, простыми словами, снятие снепшота с информацией у кого столько акций. Затем весь объем средств, зарезервинованных под дивиденды раздадут в соответствии с пропорциями в этом снепшоте. Таким образом, одинаковые по размеру дивиденды получит и тот, кто держал акцию с прошлой выплаты, и тот, кто купил ее за день до даты отсечки. Это упрощает компаниям процесс отслеживания изменения владения. Просто снимок списка акционеров в определенную дату.

В принципе, дивиденды или голосования с использованием ERC-20 токена проводятся примерно так же. В момент отсечки нужно сделать снепшот, примерно вот с такими полями (дата снепшота, адрес владельца кошелька, доля на момент снепшота, размер вознаграждения, было ли получено вознаграждение).

У этого подхода несколько сложностей:

  1. Процесс создания снепшота должен быть кем-то инициирован.

  2. Процесс должен быть атомарен и для больших реестров совладельцев может выйти за рамки допустимого потребления газа.

  3. В принципе, вместо снепшота можно сразу рассылать средства на кошельки совладельцев.

  4. Стандартный ERC-20 не дает проитерироваться по владельцам, поэтому придется использовать внешнюю логику, что нежелательно. А сделать это еще и атомарно и консистентно - отдельное искусство.

Даже любая одна из этих проблем казалась бы очень неприятной. Но их больше! И тут мы подумали про ERC-721. Владение идентифицируемым объектом. В нашем примере предположим, что все объекты у нас равнозначны и дают право на получение 1% от вырученных средств. Но сам факт того, что мы можем где-то записать ID объекта (токена), позволяет создать очень простую схему: при каждом взаимодействии с нашим контрактом пользователь платит какую-то комиссию. Она остается на счете контракта. Так же мы создаем переменные "общая сумма комиссий" и таблицу "идентификатор объекта, уже снято средств". Таким образом, в любой момент времени, не дожидаясь отсечек, совладелец может снять "общая сумма комиссий" * доля ‒ "снято". Никаких снепшотов, никаких сложных дорогих операций над множеством объектов.

Так вот я и полюбил ERC-721.

Комментарии (5)


  1. gwisp
    01.06.2022 03:16
    +2

    При таком подходе получается, что доля кратна 1%. А если делать доли более делимые, то у одного инвестора будет очень много токенов, и каждым надо будет воспользоваться по отдельности, заплатив очень много газа. Да и при 1% газа может много уходить. А ещё сложно торговать долями будет, потому что рыночная стоимость доли зависит от накопленного дохода, который постоянно меняется. Для решения той же проблемы на обычных биржах при торговле облигациями покупатель должен ещё в добавок заплатить автоматически вычисляемый накопленный купонный доход, но не знаю, есть ли что-то аналогичное в мире криптовалют.

    Кажется, следующая схема на ERC-20 была бы лучше. Но возможно я изобретаю велосипед.

    1. У каждого инвестора есть накопленный доход, также вместе с этим хранится общий доход контракта на момент расчёта накопленного дохода

    2. При переводе токенов между инвесторами накопленный доход обоих пересчитывается, используя разницу между текущим общим доходом контракта и общим доходом на момент предыдущего расчёта накопленного дохода

    3. Инвесторы забирают весь свой доход одним вызовом контракта

    Из недостатков схемы - невозможность дополнительного выпуска токенов или их сжигания, потому что при этих операциях пришлось бы пересчитать накопленный доход всех инвесторов.


    1. xni Автор
      01.06.2022 10:03

      Не подумал о таком подходе. Да, выглядит резонно!

      В случае ERC-721 в принципе тоже можно ввести "вес" токена, не обязательно там 1%. Но тогда получается какое-то прям переусложнение.


  1. mtiutin
    02.06.2022 09:45
    -1

    Чтобы решить задачу распределения дивидендов 1 транзой для ERC-20, можно адаптировать подход фармилки MasterChef (0xc2EdaD668740f1aA35E4D8f227fB8E17dcA888Cd) Там используется мультипликатор accPerShare, который показывает накопление дохода в расчете на 1 акцию. Распределение дохода = пересчитать и увеличить accPerShare. Проблемы с mint и burn акций там тоже решены и сопровождаются выплатой купонного дохода. В общем, я такую задачу вполне успешно решил на базе подхода вышеуказанного контракта.


    1. xni Автор
      02.06.2022 23:08

      Прошу прощения за минус, промахнулся с кнопкой "Ответить" и не могу изменить обратно... С меня плюс к вашему следующему комментарию просто так :)

      Посмотрел я тот контракт, и не нашел там accPerShare, это раз. Два - это вопрос о том как все же помечать что какой-то владелец уже забрал свои дивиденты, а какой-то еще нет?


      1. mtiutin
        03.06.2022 16:34

        1. конкретно в том контракте он accSushiPerShare. Сорян. Просто я их уже несколько штук видел, название токена посредине все меняют на свой лад...

        2. Фактически, пометка о том, "по куда" юзер забрал свою награду (дивиденды) делается вот здесь:
          user.rewardDebt = user.amount.mul(pool.accSushiPerShare).div(1e12);
          следующий раз, когда он будет забирать токены, это значение будет отниматься:
          uint256 pending = user.amount.mul(pool.accSushiPerShare).div(1e12).sub(user.rewardDebt);
          рекомендую сделать тестовый пример в табличке в екселе с параметрами контракта (одного пула и 2 юзеров, допустим), и расписать (по коду), как они меняются при транзакциях. так будет понятнее.