Solidity. Смарт контракты и аудит
2.63K subscribers
246 photos
7 videos
18 files
555 links
Обучение Solidity. Уроки, аудит, разбор кода и популярных сервисов
Download Telegram
Chainlink VRF. Часть 1

Следующие несколько постов будут про Chainlink VRF или про то, как сервис помогает сгенерировать случайное число.

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

Chainlink решает эту проблему по своему. Он использует несколько контрактов, которые через оракулов не только генерируют случайное число, но и могут дать подтверждение этому, записанное в блокчейн. Поэтому вы в любой момент можете убедиться, что данное число действительно рандомное.

Сервис предоставляет два метода генерации чисел: Подписной и По запросу.

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

Второй же способ подходит для тех, кому нужно получить число разово или по требованию. Другими словами, каждый раз придется отправлять запрос в chainlink вручную.

В данный момент генерация случайных чисел доступна для сети Эфира, BNB, Polygon, Avalanche и Fantom.

#chainlink #vrf #random
👍1
Chainlink VRF. Часть 2

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

В chainlink vrf помимо нашего контракта существуют еще два контракта: VRF Координатор и VRF Сервис.

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

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

Эту цепь можно представить так:

Наш контракт (отправляет запрос на число) => Координатор (порождает событие, отправляет в Сервис) => Сервис (создает число и доказательство случайности, отправляет в Координатор) => Координатор (подтверждает число и доказательство, отправляет в наш Контракт) => Наш контракт

В нашем контракте сгенерированное число записывается либо в переменную, либо в mapping.

#chainlink #vrf #random
👍1
Chainlink VRF. Часть 3

Как создать Подписной метод генерации случайных чисел?

1. Для начала нужно зарегистрироваться на сервисе по этой ссылке, нажав "Create Subscription" и подключив кошелек.

Обратите внимание, что для проведения тестов, кошелек должен быть настроен на тестовую сеть, в нашем случае goerly.

2. Затем требуется добавить Link на счет только что созданного аккаунта. Это можно сделать и позже, если вы не запросили их на chainlink до сих пор.

3. Добавление Consumers (пользователей, от которых будут поступать запросы на генерацию чисел). Сюда добавляются адреса контрактов, откуда будут идти запросы. Мы сделаем это чуть позже.

Создание аккаунта, добавление Link - все это требует наличие Эфира на счету! Добавьте его через faucets, как было написано в предыдущих постах. 

Если вы все сделали правильно, то откроется ваш личный кабинет на chainlink.

Кстати, там указан ваш ID, который нам понадобится для написания смарт контракта.

#chainlink #vrf #random
👍1
Chainlink VRF. Часть 4.1

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

Давайте пройдемся по коду.

Итак, в начале импортируются три контракта: ConfirmedOwner устанавливает нас (msg.sender), как владельца, VRFCoordinatorV2Interface - контракт Координатор для данной сети, VRFConsumerBaseV2 - обрабатывает ответ от Координатора.

Далее порождаются два event, чтобы в личном кабинете мы видели транзакции, создается структура RequestStatus, отвечающая за статусы запросов, mapping для хранения полученных чисел, а также несколько переменных для нашего ID, id последнего запроса.

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

Вообще keyhash отвечает за то, сколько газа в wei вы готовы заплатить за транзакцию. Чем больше это число, тем быстрее пройдет транзакция.

callbackGasLimit - отвечает за вызов callback функции в нашем контракте fulfillRandomWords(). Она должна быть меньше MaxGasLimit в контракте Координатора. Если указать ее слишком маленькой, то полученные сгенерированные числа просто не сохранятся в нашем контракте.

requestConfirmations - сколько подтверждений узел Chainlink должен подождать прежде чем ответить. Он должен быть в пределах Minimum и Maximum конфигурации.

numWords - сколько случайных чисел нам нужно получить. Их количество влияет на количество газа в callbackGasLimit. Будьте тут внимательны. Также это значение не должно превышать значение VRFCoordinatorV2.MAX_NUM_WORDS.  

#chainlink #vrf #random
👍1
Chainlink VRF. Часть 4.2

Далее в конструкторе устанавливается владелец контракта и передается контракт Координатор.

Также тут представлены всего три функции.

requestRandomWords() - основная функция, которая отправляет запросы на генерацию случайных чисел в контракт Координатор, создает новую запись struct в mapping, устанавливает id последнего запроса и порождает событие.

fulfillRandomWords() - это функция, которую в нашем контракте вызывает контракт Координатор, когда получает сгенерированное число. Она добавляет числа в массив и порождает событие.

getRequestStatus() - служебная функция, которая позволяет нам проверять статус того или иного запроса.

Деплой можно также сделать из Ремикса, указав наш ID личного кабинета.

После деплоя контракта, нам нужно вернуться в личный кабинет и добавить в Consumers адрес нашего только что созданного контракта, иначе постоянно будет возникать ошибка, при попытке вызвать функцию генерации числа.

Для запроса случайного числа вызываем функциюrequest RandomWords(), ждем немного пока вернется ответ, и проверяем значения в requestIds.

В личном кабинете можно увидеть информацию по транзакции.

#chainlink #vrf #random
👍1
Chainlink VRF. Часть 5

Пара слов о Link токенах во всем этом деле.

На первый взгляд может показаться, что Link вообще не участвует в наших видимых транзакциях. МЫ платим за разворачивание аккаунта, за перевод этих самых Link, за деплой контракта, за вызов функций в нем и т.д.

И за все это время ни разу не проскальзывает Link!

А его работа заключается в другом.

Помните описание цепи работы контрактов, что я делал выше? Так вот, когда в дело вступают  Координатор и Сервис, то в транзакциях между собой также используют газ: для генерации числа, записи доказательства в блокчейн, проверку доказательства и числа, и, наконец, вызов callback функции в нашем контракте.

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

И, да, Link - это своего рода тоже криптовалюта, которой торгуют на бирже.

#chainlink #vrf #random
👍1
Chainlink VRF. Часть 6

Далее рассмотрим контракт для разового получения случайного числа без создания личного кабинета и регистрации на сервисе.

Идем по этой ссылке и также открываем код в Ремиксе.

Прежде всего нужно отметить, что помимо контракта Координатора, нам нужно указывать контракт Wrapper, которого нет в Подписной модели.

Конфигурации сетей для разовых запросов можно посмотреть тут.

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

Итак, в данном коде появляются новые переменные: linkAddress и wrapperAddress, куда записываются адреса контрактов токена и wrapper. Их все можно найти в конфигурации.

Функции requestRandomWords(),  fulfillRandomWords() и getRequestStatus() делают все то же, что и описанные ранее.

И добавляется функция withdrawLink(). Сейчас объясню зачем она нужна.

Помните, при создании личного кабинета мы зачисляли на его счет некоторую сумму Link? Так вот, в разовом контракте, нам нужно перечислить туда токены после деплоя напрямую из нашего кошелька. Без этого мы не сможем вызывать функции генерации номеров.

И функция withdrawLink() нужна для того чтобы вернуть неиспользованные Link обратно на кошелек с контракта, если таковые будут после запроса.   

#chainlink #vrf #random
👍1
Chainlink VRF. Часть 7

В завершении темы VRF стоит упомянуть еще несколько моментов.

1. В Подписной модели вы можете создать отдельный контракт, который будет управлять Consumers. Вам больше не придется заходить в личный кабинет и вручную добавлять каждый адрес контракта. Все это можно автоматизировать.

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

2. В контракте можно запрашивать число "между % и %", например, между 1 и 50. Для этого потребуется добавить следующую строку в функцию fulfillRandomWords():

s_randomRange = (randomWords[0] % 50) + 1;

Однако, как я понял, это работает в случае единичного запроса. Для нескольких чисел придется писать цикл.

3. Можно получать от 1 до 200-500 случайных чисел за раз, в зависимости от конфигураций сети.

4. Если вы позволяете делать запросы на случайное число другим контрактам, то можно отслеживать этот процесс с помощью добавление нового mapping, куда будут записываться id запроса и адрес контракта.

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

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

Далее мы переходим к теме подключение к API через Chainlink.

#chainlink #vrf #random
👍1