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

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

Смарт-контракт на Solidity: Часть 3 — визитка — address, конструктор, переменная msg

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

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

В предыдущем уроке мы написали смарт-контракт визитку. В этом уроке мы улучшим нашу визитку, а в частности запретим всем кроме владельца изменять данные внутри визитки. А также затронем темы:

  • переменная msg
  • конструктор контракта
  • тип address
  • исключение throw

Код нашей визитки из предыдущего урока

pragma solidity ^0.4.13;

contract BusinessCard {

    mapping (bytes32 => string) data;

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

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

}

Напомню — методом getData мы можем получить значение, записанное ранее на визитке. А метод setData позволял изменить значение.

После того как смарт-контракт будет создан внутри сети Ethereum он будет доступен любому человеку в сети. Это значит что любой участник сети Ethereum может выполнить как функцию getData так и функцию setData. Таким образом мы имеем опасность того что другой пользователь вызвав функцию setData изменит данные на нашей визитке. А мы бы хотели чтобы менять их мог только владелец визитки. Давайте решим эту проблему!

Внутри контракта нам доступна глобальная переменная msg. Это структура с несколькими полями. С этими полями мы будем знакомится по мере необходимости. Сейчас мы познакомимся с полем sender. Итак msg.sender — это адрес того, кто выполняет контракт в данный момент. Того кто вызвал функцию. Тип этого поля address.

Таким образом для того чтобы запретить менять данные визитки посторонним лицам контракту достаточно проверить — является ли адрес того кто выполняет контракт в данный момент адресом владельца визитки. Т.е. если msg.sender равен адресу владельца визитки то мы выполняем setData. В противном случае сообщаем об ошибке.

И тут возникает вопрос. Как получить адрес владельца визитки? При создании контракта вызывается специальная функция — конструктор. Она имеет такое же название как и сам контракт и ничего не возвращает.

function ИмяКонтракта() {
     ...
}

Мы уже знаем что в msg.sender хранится адрес того кто выполняет контракт в данный момент. Поскольку тот кто создает визитку и есть владелец визитки, то нам достаточно получить в конструкторе msg.sender и сохранить его внутри контракта для последующего сравнения.

Поправим наш контракт:

pragma solidity ^0.4.13;

contract BusinessCard {

    mapping (bytes32 => string) data;

    address owner;

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

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

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

}

Теперь наш контракт содержит переменную owner в которую конструктор сохраняет адрес создателя-владельца визитки. А в функции setData e у нас появилось условие:

if(msg.sender != owner) 
            throw;

Незнакомое нам слово throw заставляет контракт прекратить работу. В последних версиях solidity не рекомендуется использовать throw. А для проверки какого-либо условия прекращения работы функции рекомендуют использовать конструкцию require(условие). Если условие не выполняется то функция останавливается. Между способами остановки работы функции есть существенная разница, но мы ее пока рассматривать не будем. Просто перепишем наш код с require.

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 getData(string key) constant returns(string) {
        return data[sha3(key)];
    }

}

Давайте теперь проверим работу нашего контракта. Создайте контракт в сети Ethereum (см. урок 1). Обратите внимание на поле Account.

Поле account это адрес вашего аккаунта. Именно от его имени вы в данный момент работаете и именно от его имени был создан контракт. Если вы сейчас вызовите setData с какими либо данными (например: «email», «cromlehg@gmail.com») то данные внутри контакта успешно поменяются.

В целях тестирования Remix позволяет сменить адрес аккаунта. В выпадающем списке account выберите любой другой адрес. А теперь попробуйте вызвать setData и вы получите сообщение об ошибке — исключение. Контракт не позволил нам изменить данные потому что адрес владельца визитки другой.

Статус последней операции remix отображает в консоле.

Итак, мы в этом уроке узнали как получить адрес того кто выполняет контракт в данный момент. Узнали что такое конструктор. И что самое важное — научились ограничивать доступ к функциям контракта и тестировать!

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

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