В нашем четвертом уроке мы познакомимся с последними темами перед тем как приступить к написанию нашей собственной монеты! Темы этого урока — наследование и модификаторы.
Предыдущий урок можно посмотреть тут.Полный список уроков тут.
Представьте что вам потребовалось сменить адрес кошелька. Тогда вам придется и поменять адрес владельца визитки. А для этого нам потребуется дописать одну функцию. И чтобы ее не мог вызвать кто попало мы вначале ее кода сделаем проверку на адрес владельца.
Теперь весь код нашей визитки выглядит так:
У нас уже есть две функции, которые содержат одинаковый код проверки владельца. Сейчас у нас контракт довольно простой. Но на практике контракты значительно больше. Поэтому, возможно, в дальнейшем у нас будет больше функций с проверкой владельца. Чтобы каждый раз не писать эту проверку проще было бы вынести этот код куда-нибудь в одно место. Для этого используют модификаторы.
Чтобы к функции применить модификатор нужно после скобок поставить имя модификатора
Если в заголовке функции стоит модификатор, то функция выполняется внутри кода модификатора на месте где стоит символ «_».
Посмотрим как использовать модификатор на примере нашей визитки:
Мы видим что из функций setData и transferOwnership исчезла проверка на владельца. Но в заголовке у них появилось имя модификатора onlyOwner. Давайте посмотрим на код onlyOwner.
Он у нас состоит из двух строк. В первой проверяется является ли исполнитель владельцем. Если не является, то мы выйдем из функции. А если является то будет исполнена вторая строчка, в которой вместо магического символа «_» будет исполнен код функции которая сейчас выполняется с нашим модификатором.
Теперь, если нам потребуется написать функцию, которая может быть исполнена только владельцем контракта, то нам достаточно добавить onlyOwner к ее заголовку как это сделано в setData и tranferOwnership.
В пределах одного контракта мы решили проблему дублирования кода. А теперь представьте что у нас несколько контрактов. У всех у них есть функции с проверкой на владельца. Получается что в каждом контракте придется писать код модификатора. А хотелось бы опять же вынести весь дублирующий код в одно место. Тут нам на помощь приходит наследование.
Контракты в solidity могут наследоваться друг на друга. Это значит что функции и переменные контракта от которого мы наследуемся будут доступны в контракте который наследует.
Контракт A наследуется от контрактов B, C и D.
Рассмотрим на примере нашей визитки. Вынесем код, который отвечает за проверку владельца в контракт Ownable и унаследуем от него нашу визитку.
Как видите код нашей визитки значительно упростился, а в заголовке появилось «is Ownable». Если вы заметили, то в коде визитке сейчас отсутствует конструктор. Его мы убрали потому как он содержал код сохранения владельца визитки. Этот код мы перенесли в Ownable. Стоит отметить что если и в контракте наследнике и в контракте предке есть конструктор, то сначала будет исполнен конструктор предка, а потом наследника. Т.е. в нашем случае сначала Ownable а потом BuisnessCard.
Теперь если у нас появятся другие контракты, которые требуют проверки доступа, то нам достаточно наследоваться от Ownable в котором мы уже написали все необходимое. Шаблон наследования от Ownable очень распространенная практика в написании смарт-контрактов.
На этом пока все. Продолжение читать тут. Предыдущий урок тут.
Если у вас возникли вопросы то можете смело писать на электронную почту (раздел «контакты«). Также приветствуется критика.
А не перепутано ли местонахождение «_», в псевдокоде модификатора и функции для него?
modifier имя_модификатора() {
код_модификаторы
}
function имя_функции() имя_модификатора {
…
_;
…
}
Судя по дальнейшему описанию перепутано, а иначе какой смысл несет «_» в теле функции?
Верно, спасибо, исправил.
И чтобы ее не !могу! вызвать кто попало мы вначале ее кода сделаем проверку на адрес владельца.
Чтобы к функции применить модификатор нужно !в после! скобок поставить имя модификатора
Спасибо. Исправил.
modifier onlyOwner() public {
require(msg.sender == owner);
_;
}
Вот тут слово public вызывает ошибку компилятора в Remix
(последний вариант визитки в этом уроке)
если убираю то все норм.
в спецификации языка для модификаторов не указаны дополнительные модификаторы типа public, видимо у автора опечатка
Подскажите как додать в контракт BusinessCard для функции setData модификатор проверки введенного пароля (подумать как это можно реализовать используя имеющиеся знания)