Содержание

Простой смарт-контракт на Solidity

Хранилище (storage)

pragma solidity ^0.4.0;

contract SimpleStorage {
    uint storedData;

    function set(uint x) public {
        storedData = x;
    }

    function get() public constant returns (uint) {
        return storedData;
    }
}

В первой строке указано, что код написан для Solidity версии 0.4.0 или новее (вплоть до версии 0.5.0, но не включая ее). Это должно гарантировать, что контракт не будет вести себя по-другому с новой версией компилятора. Ключевое слово pragma, называется так, потому что pragma — это инструкция для компилятора о том, как обрабатывать код.

Контракт на Solidity — это набор кода (его функции) и данных (его состояние), который находится на конкретном адресе в блокчейн Ethereum. Строка uint storedData; объявляет глобальную переменную storedData типа uint (беззнаковое целое из 256 бит). Можно считать, что это один слот в базе данных, который может быть запрошен и изменен по вызову функции из кода, который управляет базой данных. В случае с Ethereum, это всегда владеющий контракт (owning contract). И в этом случае, функции set и get можно использовать для изменения и возврата значения переменной.

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

Этот контракт пока ничего не делает, кроме того, что позволяет кому-то хранить единственное число, которое доступно любому человеку в мире без (возможного) способа предотвратить публикацию этого номера. Конечно, любой может просто вызвать set снова с другим значением и перезаписать число, но число будет по-прежнему сохранено в истории блокчейн.

Примечание

Все идентификаторы (имена контрактов, имена функций и имена переменных) ограничены ASCII набором символов. В строковых переменных можно хранить данные в формате UTF-8.

Предупреждение

Нужно быть осторожными с использованием текста Unicode, так как похожие (или даже идентичные) символы могут иметь разные кодовые точки и как таковые будут закодированы как разные байтовые массивы.

Пример криптовалюты

Следующий контракт реализует простейшую форму криптовалюты. Можно создавать монеты из воздуха, но только тот, кто создал контракт, сможет это делать. Кроме того, любой может отправить монеты кому-то другому без регистрации с помощью логина и пароля. Все, что для этого нужно, иметь пару ключей Ethereum.

pragma solidity ^0.4.0;

contract Coin {
    // Ключевое слово public делает эти переменные
    // читаемыми отовсюду.
    address public minter;
    mapping (address => uint) public balances;

    // События позволяют оповещать клиенты об
    // изменениях.
    event Sent(address from, address to, uint amount);

    // Это конструктор, чей код выполняется только
    // контракт создается.
    function Coin() public {
        minter = msg.sender;
    }

    function mint(address receiver, uint amount) public {
        if (msg.sender != minter) return;
        balances[receiver] += amount;
    }

    function send(address receiver, uint amount) public {
        if (balances[msg.sender] < amount) return;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        Sent(msg.sender, receiver, amount);
    }
}

Этот контракт представляет несколько новых концепций. Они описаны ниже.

Строка address public minter; объявляет глобальную переменную, которая доступна публично. Тип address — это 160-битное значение, с которым запрещены любые арифметические операции. Он подходит для хранения адресов контрактов или пар ключей, принадлежащих физическим лицам. Ключевое слово public автоматически генерирует функцию, которая получает доступ к текущему значению глобальной переменной. Без этого ключевого слова другие контракты не будут иметь доступ к переменной. Функция будет выглядеть примерно так:

function minter() returns (address) { return minter; }

Конечно, добавление функции точно так же не будет работать, потому что у нас будет функция и глобальная переменная с тем же именем.

Следующая строка mapping (address => uint) public balances; также создает public глобальную переменную, но этот тип данных немного сложнее. Маппинги можно рассматривать как хэш-таблицы, которые фактически инициализируются так, что существуют все возможные ключи, и они сопоставляются значениям, чьи байт-представления — все нули. Это не совсем точная аналогия, поскольку невозможно получить ни список всех ключей, ни список всех значений. Поэтому нужно или держать в голове (или лучше, сохранить список или использовать более расширенный тип данных) то, что добавляется в маппинг, или использовать его в контексте, где это не нужно. Геттер-функция созданная через ключевое слово public в этом случае будет немного сложнее. Примерно она выглядит следующим образом:

function balances(address _account) public view returns (uint) {
    return balances[_account];
}

Как видно, эту функцию можно легко использовать для запроса баланса некоторого аккаунта.

Строка event Sent(address from, address to, uint amount); объявляет так называемое событие, которое вызывается в последней строке функции send. Пользовательские интерфейсы (а также, конечно, серверные приложения) могут прослушивать события, которые запускаются в блокчейн, без значительных затрат. Как только событие запущено, слушатель также получает аргументы from, to и amount, что позволяет легко отслеживать транзакции. Чтобы прослушать это событие, нужно использовать:

Coin.Sent().watch({}, '', function(error, result) {
    if (!error) {
        console.log("Coin transfer: " + result.args.amount +
            " coins were sent from " + result.args.from +
            " to " + result.args.to + ".");
        console.log("Balances now:\n" +
            "Sender: " + Coin.balances.call(result.args.from) +
            "Receiver: " + Coin.balances.call(result.args.to));
    }
})

Здесь нужно обратить внимание, как автоматически сгенерированная функция balances вызывается из пользовательского интерфейса.

Функция Coin — это конструктор, который запускается во время создания контракта, и не может быть вызван впоследствии. Он постоянно хранит адрес того, кто создал контракт: msg (вместе с tx и block) — это магическая глобальная переменная, которая содержит несколько свойств, предоставляющих доступ к блокчейну. msg.sender — это всегда адрес, откуда пришел текущий (external) вызов функции.

Функции mint и send в конце контракта могут быть вызваны пользователями или контрактами. Функцию mint может вызвать только тот, кто создал контракт. А функция send может быть вызвана кем-угодно из тех, у кого уже есть какое-то количество данных монет. Функция send отправляет указанное количество монет на другой аккаунт.

Материал был полезен? Поделитесь в соц. сетях:
Логотип echain.ru

Комментарии

  1. Поправьте пожалуйста: о тоК
    тут — “pragma — это инструкция для компилятора о ток, как обрабатывать код.”

Добавить комментарий

Ваш e-mail не будет опубликован.