Алгоритмы сnейкинга в MasterChef и Synthetix распределяют фиксированный пул вознаграждений между пользователями в соответствии с их взвешенными по времени вкладами в пул. Для того чтобы сэкономить на газе, алгоритмы используют кумулятивный счетчик вознаграждений на уровне токенов и откладывают распределение вознаграждений.
Представьте, что у нас есть фиксированный пул из 100 000 токенов REWARD, который мы хотим справедливо распределить между пользователями в период от блока 1 по 100 блок.
Например, на момент конкретного блока стейкинг у пользователей был следующим:
| Name | Amount Staked | % of Pool |
| :-——-- | :------———-----: | --——-----: |
| Alice | 100 | 25 |
| Bob | 100 | 25 |
| Chad | 200 | 50 |
Тогда токены Rewards распределятся следующим образом:
| Name | Amount Staked | % of Pool | Rewards distribited |
| :-——-- | :----————-----: | --——-----: | ---———--------------: |
| Alice | 100 | 25 | 250 |
| Bob | 100 | 25 | 250 |
| Chad | 200 | 50 | 500 |
P.S. Токен Reward и токен стейкинга (тот же WETH или USDT) могут быть разными или одними и теми же в разных случаях. Для ясности, мы будет называть их именно Reward и просто Token.
Прежде чем рассказывать дальше о том, как же идет подсчет токенов для распределения, необходимо сказать, что отправлять транзакцию каждый блок для распределения вознаграждения вообще непрактично.
Обычно для авто запросов в блокчейн используют ботов (программы, которые могут в заданный момент отправлять транзакцию). Однако это хреновое решение.
Как минимум, потому что нет достаточно надежного способа обеспечить включение транзакций в каждый блок. Если бот пропустит один блок, то пользователи получат меньшее вознаграждение, чем ожидают.
Эта стратегия также повлечет за собой большие транзакционные сборы.
Отказавшись от этой системы, мы можем создавать «догоняющие» вознаграждения за блоки, в которых вознаграждения не были распределены.
Предположим, мы храним переменную в lastUpdateBlockNumber, которая отслеживает последний раз, когда выдавалось вознаграждение. Мы могли бы вычислять количество блоков с момента последнего вознаграждения как
block.number - lastUpdateBlockNumber;
Другими словами, мы можем пропустить несколько блоков, в которых мы распределяем вознаграждение, и «догнать» их, когда мы действительно делаем это.
Но даже при этом способе, у нас до сих пор нет хорошего способа распределить награды, которые мы только что сминтили, между всеми стейкерами в соответствии с их процентной долей.
Кроме того, мы не знаем, были ли балансы токенов постоянными в течение предыдущего интервала, с момента последнего распределения вознаграждения.
Например, что если Чад знал, что мы собираемся измерить остатки на блоке 100, и сделал большой депозит на блоке 99, чтобы получить большую долю вознаграждения?
Эту проблему оказалось легко решить. Как? Узнает в следующем посте цикла.
#Sushiswap #MasterChef #staking