Бегом по Chainlink
Сегодня мы пробежимся по работе Chainlink на примере GET запроса из их документации
Начнем
Мы не будем сильно останавливать на самой компании Chainlink, просто скажу что это конторка которая предоставляет удобную систему пользования оракулами, о которых мы сегодня и поговорим
Как я уже сказал в начале, мы будем делать GET запрос на один сайт, чтобы узнать там необходимые нам значения и после этого вернуть их в блокчейн
Основные функции нашего контракта выглядят так:
С полным контрактом можно ознакомиться тут ТЫК
Давайте взглянем на функцию requestVolumeData
. В ней мы создаем запрос состоящий из jobId (номер работы, чтобы нода чейнлинка могла понять что делать, у каждой операции свой номер), адрес нашего контракта (чтобы нода знала куда потом слать ответ от GET), селектор функции fulfill
(чтобы нода знала, по какому селектору в нашем контракте надо обращаться, когда она будет присылать ответ от GET. В самой функции fulfill
у нас идет запись в поле volume)
Далее у нас идут методы .add
для req
, в которых мы дописываем параметры, необходимые для GET запроса
В конце мы вызываем sendChainlinkRequest
и попадаем в веселый мир контрактов чейнлинка
Через вызов sendChainlinkRequest
мы вызываем sendChainlinkRequestTo
, он с одним дополнительным параметром
В самом sendChainlinkRequestTo
мы собираем request (запрос) в красивый вид + добавляем необходимые для этого запроса параметры, например селектор ChainlinkRequestInterface.oracleRequest.selector
, чтобы в будущем наш запрос также понимал по каким функциям дальнейшего контракта обращаться
В конце мы вызываем _rawRequest
Тут вы создаем id для нашего запроса, чтобы потом его можно была найти, а после делаем делаем вызов функции на токен $link (на контракт токена $link), а именно вызываем функцию transferAndCall
(туда мы засовываем адрес оракула, который будет это все дело обрабатывать), комиссионные (чейнлинк не бесплатно работает, а требует некоторого количества $link для совершения операций) и наш сформированный запрос
В функции transferAndCall
мы делаем трансфер токенов на адрес оракула (комиссионные), после чего вызываем contractFallBack
, в который передаем адрес оракула, комиссионные и наш запрос
Тут мы видим создание переменной receiver типа ERC677Receiver
(ERC677 - специальный стандарт токенов, который вместе с трансфером токенов позволяет передавать данные). После мы вызываем метод onTokenTransfer, куда у нас идет адрес токена $link (msg.sender), комиссионные и наш запрос
Тут обойдемся кратким пояснением - мы делаем delegatecall
на этот же контракт (контракт оракула) по нашей дате (вот за этим нам и нужен был селектор функции) и тем самым вызываем oracleRequest
Тут мы просто делаем вызов функции _verifyAndProcessOracleRequest
, которая возвращает нам номер нашего запроса и таймлимиты
Тут мы по факту можем все скипнуть, так тут просто идет формирование таймлимита (expiration) и формирование конечного id запроса + наш запрос окончательно формируется, чтобы нода могла точно определить по какому адресу и по какой функции надо будет возвращать response
Важный момент! Все это время пока мы вызвали кучу всех этих функций, нода чейнлинка слушала все emit и уже готовила ответ
На данном скриншоте мы делаем вызов requestVolumeData и получаем такое поле на etherscan в поле events у контракта
После чего на следующем блоке у нас появляются новые записи в events, которые выглядят так
Верхние два поля и есть ответ от нашего оракула, который обратился по адресу нашего контракта и по нами заданной сигнатуре и изменил параметры, которые мы его просили!
Репозиторий Chainlink - https://github.com/smartcontractkit/chainlink