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

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

Смарт-контракт на Solidity: Частина 4 — візитка — наслідування та модифікатори

отредактировано December 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 {
      ...
}

Контракт А наслідується від контрактів 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 дуже розповсюджена практика в написанні смарт-контрактів.

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

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