Привет, незнакомец!

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

Смарт-контракт на Solidity: Часть 4 — визитка — наследование и модификаторы

отредактировано November 2017 Раздел: Смарт Контракты

Серия уроков были взяты с сайте inaword.ru

В нашем четвертом уроке мы познакомимся с последними темами перед тем как приступить к написанию нашей собственной монеты! Темы этого урока — наследование и модификаторы.

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

    function transferOwnership(address newOwner) {
            require(msg.sender == owner);
            owner = newOwner;
    }

Теперь весь код нашей визитки выглядит так:

pragma solidity ^0.4.13;

contract BusinessCard {

    mapping (bytes32 => string) data;

    address owner;

    function BusinessCard() {
        owner = msg.sender;
    }

    function setData(string key, string value) {
        require(msg.sender == owner);
        data[sha3(key)] = value;
    }

    function transferOwnership(address newOwner) {
        require(msg.sender == owner);
    owner = newOwner;
    }

    function getData(string key) constant returns(string) {
        return data[sha3(key)];
    }

}

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

    modifier имя_модификатора() {
          код_модификатора
          _;
    }

Чтобы к функции применить модификатор нужно после скобок поставить имя модификатора

function имя_функции() имя_модификатора {
     ...
}

Если в заголовке функции стоит модификатор, то функция выполняется внутри кода модификатора на месте где стоит символ «_».

Посмотрим как использовать модификатор на примере нашей визитки:

pragma solidity ^0.4.13;

contract BusinessCard {

    mapping (bytes32 => string) data;

    address owner;

    function BusinessCard() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    function setData(string key, string value) onlyOwner {
        data[sha3(key)] = value;
    }

    function transferOwnership(address newOwner) onlyOwner {
        owner = newOwner;
    }

    function getData(string key) constant returns(string) {
        return data[sha3(key)];
    }

}

Мы видим что из функций setData и transferOwnership исчезла проверка на владельца. Но в заголовке у них появилось имя модификатора onlyOwner. Давайте посмотрим на код onlyOwner.

modifier onlyOwner() {
        require(msg.sender == owner);
        _;
}

Он у нас состоит из двух строк. В первой проверяется является ли исполнитель владельцем. Если не является, то мы выйдем из функции. А если является то будет исполнена вторая строчка, в которой вместо магического символа «_» будет исполнен код функции которая сейчас выполняется с нашим модификатором.

Теперь, если нам потребуется написать функцию, которая может быть исполнена только владельцем контракта, то нам достаточно добавить onlyOwner к ее заголовку как это сделано в setData и tranferOwnership.

В пределах одного контракта мы решили проблему дублирования кода. А теперь представьте что у нас несколько контрактов. У всех у них есть функции с проверкой на владельца. Получается что в каждом контракте придется писать код модификатора. А хотелось бы опять же вынести весь дублирующий код в одно место. Тут нам на помощь приходит наследование.

Контракты в solidity могут наследоваться друг на друга. Это значит что функции и переменные контракта от которого мы наследуемся будут доступны в контракте который наследует.

contract A is B, C, D {
      ...
}

Контракт A наследуется от контрактов B, C и D.

Рассмотрим на примере нашей визитки. Вынесем код, который отвечает за проверку владельца в контракт Ownable и унаследуем от него нашу визитку.

pragma solidity ^0.4.13;

contract Ownable {

    address owner;

    function Ownable() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    function transferOwnership(address newOwner) onlyOwner {
        owner = newOwner;
    }

}

contract BusinessCard is Ownable {

    mapping (bytes32 => string) data;

    function setData(string key, string value) onlyOwner {
        data[sha3(key)] = value;
    }

    function getData(string key) constant returns(string) {
        return data[sha3(key)];
    }

}

Как видите код нашей визитки значительно упростился, а в заголовке появилось «is Ownable». Если вы заметили, то в коде визитке сейчас отсутствует конструктор. Его мы убрали потому как он содержал код сохранения владельца визитки. Этот код мы перенесли в Ownable. Стоит отметить что если и в контракте наследнике и в контракте предке есть конструктор, то сначала будет исполнен конструктор предка, а потом наследника. Т.е. в нашем случае сначала Ownable а потом BuisnessCard.

Теперь если у нас появятся другие контракты, которые требуют проверки доступа, то нам достаточно наследоваться от Ownable в котором мы уже написали все необходимое. Шаблон наследования от Ownable очень распространенная практика в написании смарт-контрактов.

На этом пока все. Продолжение читать тут.

Войдите или Зарегистрируйтесь чтобы комментировать.