"Каждому по труду!" или как распределить награды в блокчейне с использованием с…
👁 508
Для многих криптопроектов возникает типичная проблема: "Проект каждый блок генерирует награду, которая затем распределяется среди всех пользователей в соответствии с их долями вложенных средств. Как определить, сколько каждый пользователь сможет получить в будущем?"
На первый взгляд, решение кажется простым: разделить количество вложенных средств пользователя на общую сумму вложенных средств и умножить полученную долю на награду за один блок и продолжительность времени. Вроде проблема решена и пост можно заканчивать, но как бы не так!
Что, если пользователь менял свой вклад в течение периода начисления наград? В таком случае, нам придется пересчитывать доли всех пользователей при каждом изменении вложений, вычислять текущую награду и сохранять ее. Ну вот теперь то проблема решена, уже можно расходиться? К сожалению опять нет, так как в смарт-контрактах отсутствуют циклы совсем или они сильно ограничены количеством повторений.
Ну и как тогда решить эту задачу? Ответ заключается в использовании интегралов.
Да, мне тоже первое, что приходит на ум при слове «интеграл»* это старый анекдот «Алгебра мне в жизни понадобилась один раз, чтобы сделать из проволоки интеграл и достать ключи из унитаза», но не всё так страшно на практике.
Давайте рассмотрим, как можно решить нашу задачу.
Мы будем вычислять начисленные награды с момента первого блока, в котором началась выдача наград. Размер награды за один блок будет записан как
RewardPerBlock, а первое значение интеграла (LastTotalIntegral – последнее общее значение интеграла; LastUserIntegral – последнее значение интеграла для пользователя) будет равно 0. Нам также понадобится информация о том, сколько всего средств было вложено (LastTotalAmount), и сколько средств вложено пользователем (LastUserAmount).
Логика расчетов следующая: каждый раз, когда какой-либо пользователь вносит или выводит свои средства или забирает накопившиеся награды, нам нужно обновлять общее значение интеграла и для пользователя, а также обновлять общее количество средств и количество средств пользователя. Мы также должны сохранить высоту блока, на которой последний раз выполнилось одно из этих действий (LastHeight).
Формула для расчета интеграла выглядит следующим образом:CurrentTotalIntegral = LastTotalIntegral + RewardPerBlock * (CurrentHeight – LastHeight) / LastTotalAmount
Теперь, как мы можем вычислить, какую награду пользователь может получить?
Для этого используем формулу:UserRewards = LastUserAmount * (CurrentTotalIntegral – LastUserIntegral)
"Вы видели интеграл? А он есть!"
С помощью таких простых формул можно рассчитывать вознаграждение для каждого пользователя, учитывая их доли вкладов на протяжении всего периода.