Solidity | События и кастомные модификаторы
Всем привет, сегодня поговорим о кастомных модификаторах, о событиях и разберемся что такое за функция reqiere() по подробнее.
Сначала расскажу про require() и его друзей. То что было в прошлой статье, чтоб появилось понимание, а потом перейдем уже к теме.
require() assert() revert()
Начну с того, что все эти функции откатывают транзакцию, если можно так сказать. Они работает как if else и сохраняют читабельность кода. Но у каждой из них есть свои особенности и применения, о которых я попробую рассказать.
Revert() откатывает транзакцию с причиной revert. Обычно эту функцию используют, когда нужно откатить транзакцию в коком-то сложном месте, где много условий или в сложных случаях.
Главная прелесть в том, что при откате транзакции мы получим весь не израсходованный газ обратно себе. Работает наверно как return 0 в c++. Используется достаточно редко, потому что каждая лишняя переменная или условие в solidity это деньги, поэтому лучше не загромождать код лишней фигней, без которой можно легко обойтись.
Assert() уже работает более интересно. В него ты вставляешь условие, при котором будет вызвана эта функция и, если условие не проходит, то транзакция откатиться.
Например: assert(owner == msg.sender). Если условие не выполнится, то будет откат транзакции
Главный минус ,и почему ее лучше вообще не использовать - это то, что она не возвращает газ за транзакцию. То есть майнер скушает твои денюшки на халяву (хотя щас уже нет, потому что у них вроде фиксированное вознаграждение, но это не точно). Ну в общем assert() обычно используют в тех случаях, когда у нас есть условие которое не должно сработать, а если сработало, то у нас серьезные проблемы в безопасности или логике контракта.
Require() самая дружелюбная и популярная из всех трех друзей. Она работает по прицепу assert(), то есть нужно какое-то условие для ее срабатывания, но еще и можно указать причину.
То есть, если отправитель транзакции не овнер, то откатываем транзакцию с причиной: "not an owner!". Еще ее удобство в том, что она как и revert() возвращает не использованный газ обратно нам. В общем ее нужно юзать всегда, очень удобная штука.
modifier()
modifier() - это модификаторы, на подобии Public или private, но тут мы уже будем писать условия выполнения функции сами.
Как можно заметить, что modifire() пишутся как функции. У них есть тело, можно передать аргумент. В данном случае мы промеряем является ли msg.sender овнером. Потом мы пишем волшебный символ: _; это обозначение говорит нам вызвать функцию. Ну и добавляем модификатор в функцию.
Давайте еще рассмотрим пример:
Пример от болды, но показываю для того чтоб видно было некоторые моменты.
У нас есть модификатор checkFunc(), сразу можно заметить, что мы можем неограниченное количество модификаторов засовывать в функцию. Так же мы передаем аргумент num, как и в функцию. Вызывать функцию при помощи _; можно тоже столько раз, сколько мы хотим. Как в примере.
В целом это очень удобная вещь, если нам нужно проверять какое-то условие в разных функциях, чтоб не писать каждый раз require() что-то там.
event() emit()
event() - это события, в которые мы передаем аргументы и отлавливаем изменения в блокчейне. Обычно event() используют для работы на фронтенде. Но мы об этом поговорим чуть позже. Сейчас просто рассмотрим как это работает именно в блокчейне.
Как мы можем заметить, у нас есть в функции слово emit(), это и есть наша так скажем подпись на событие event() выше. Мы можем передавать туда любые значения (в нашем случае это адрес и число). Так же мы можем проиндексировать поле для того, чтоб искать эти аргументы по их индексу.
Мы могли написать так: event (address indexed, uint)
Примечание: проиндексировать можно только ТРИ поля в одном event()
На этом я думаю можно закончить. Разобрались наконец в require(), узнали о костюмных модификаторах и событиях. Дальше больше.
tg: мой телеграмчик)