Я должен признать, что изучение эозио - это не прогулка по парку, и я понимаю, почему многие люди говорят, что у него крутая кривая обучения. Поскольку программное обеспечение eosio продолжает интенсивно и быстро развиваться, существует ограниченная документация и несколько рабочих примеров, на которые можно ссылаться. Я несколько раз попадал в тупик и хотел бы помочь улучшить опыт следующего разработчика, который придет. В этой статье я рассмотрю контракт «eosio.token», разбив его на отдельные части.

Откройте для себя и ознакомьтесь с лучшим программным обеспечением Blockchain

Что такое контракт eosio.token?

Контракт eosio.token позволяет создавать множество разных токенов. Это дает каждому возможность создавать и передавать токены. Каждый токен должен быть выпущен учетной записью «эмитента». Поскольку учетные записи могут включать в себя несколько сторон, вы можете использовать обычную учетную запись с владельцем и активными разрешениями или настраиваемую учетную запись для создания и управления токеном. Каждый токен относится к типу asset и выглядит следующим образом:

1000000000.0000 SYS

1.0000 SYMBOL

0.10 SYS

assettype - это число (которое, если я правильно помню, может достигать 18 десятичных знаков) и символ, который может состоять из 1–7 заглавных букв. В этом контракте есть три действия, которые вы можете использовать для взаимодействия с ним. Это: создание, выпуск и передача.

Create используется для определения характеристик нового токена. Это включает в себя символ токена (asset), максимальное количество и учетную запись, разрешенную для выпуска токена. Create также сохранит новую конфигурацию токена в блокчейне. Это означает, что хранилище для новой конфигурации токена должно быть кем-то зарезервировано. Как вы увидите позже, учетная запись, на которой развертывается этот контракт (в нашем случае «eosio.token»), также будет оплачивать хранилище конфигурации токенов.

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

Передача позволяет одной учетной записи передавать токены в другую.

Развертывание контракта

Первое, что вам следует знать, это то, что каждый смарт-контракт eosio принадлежит одной учетной записи eosio. Контракт - это в основном объект, с которым могут взаимодействовать другие учетные записи. Контракты содержат «действия», которые запускают код в цепочке блоков. Контракты имеют прямой доступ для хранения, удаления и обновления данных в цепочке блоков.

Для переноса действия в контракт требуется авторизация по крайней мере одной учетной записи. В зависимости от сложности контракта могут потребоваться дополнительные учетные записи и разрешения. Учетная запись может состоять из одного или нескольких лиц, настроенных в конфигурации на основе разрешений. Смарт-контракты могут выполняться только одной учетной записью, а одна учетная запись может иметь только один смарт-контракт. Лучше всего давать учетной записи и контракту одно и то же имя (в нижнем регистре).

Прежде чем вы сможете взаимодействовать с контрактом eosio.token, вам необходимо создать учетную запись с тем же именем и развернуть контракт в этой учетной записи.

Начните с создания учетной записи

$cleos create account eosio eosio.token <OWNER-KEY> <ACTIVE-KEY>

Затем составляем договор

$cd eos/contract/eosio.token

$eosiocpp -o eosio.token.wast eosio.token.cpp

Наконец, разверните контракт в учетной записи

$cleos set contract eosio.token ../eosio.token

Вы можете убедиться, что контракт был развернут с помощью

$cleos get code eosio.token

Архитектура контракта

Контракт разбит на два файла: «eosio.token.cpp» и «eosio.token.hpp». Файл «.hpp» определяет класс контракта, действия и таблицы, а файл «.cpp» реализует логику действий. Давайте сначала посмотрим на класс контракта, который будет использоваться для создания экземпляра объекта контракта. (Я удалил остатки кода из ‘eosio.token.hpp’)

Конструктор и действия определены как общедоступные функции-члены. Конструктор принимает имя учетной записи (которая будет учетной записью, на которой развернут контракт, также известной как eosio.token) и устанавливает для него переменную contract. Обратите внимание, что этот класс наследуется от «eosio :: contract».

Таблицы и вспомогательные функции предоставляются как закрытые члены. Две встроенные функции определены внизу, но никогда не используются. Это оставляет нам важные функции sub_balance() и add_balance(). Они будут вызваны действием передачи.

Таблицы

Определены две таблицы: accounts и stat. Таблица accounts состоит из разных account объектов, каждый из которых содержит баланс для разных токенов. Таблица stat состоит из currency_stats объектов (определенных struct currency_stats), которые содержат поставку, max_supply и эмитента. Прежде чем продолжить, важно знать, что этот контракт будет содержать данные в двух разных областях. Таблица accounts привязана к учетной записи eosio, а таблица stat привязана к имени символа токена.

Согласно определениям «eosio :: multi_index», «code» - это имя учетной записи, имеющей разрешение на запись, а «scope» - это учетная запись, в которой хранятся данные.

Область видимости - это, по сути, способ разделения данных в контракте, чтобы они были доступны только в пределах определенного пространства. В контракте токена каждая учетная запись eosio используется в качестве области accounts таблицы. Таблица accounts - это мультииндексный контейнер, который содержит несколько account объектов. Каждый объект account индексируется своим символом токена и содержит баланс токена. Когда вы запрашиваете accountsтаблицу пользователей, используя их область видимости, возвращается список всех токенов, по которым у пользователя есть баланс.

Вот как я это представляю.

Также есть вторая таблица под названием stat. Эта таблица будет содержать статус существующего токена. Новые токены создаются в их собственной области имен символов. В области видимости находится таблица stat, содержащая объект currency_stats. В отличие от таблицы accounts, которая содержит множество различных account объектов, таблица stat содержит только один объект currency_stats для данного символа токена.

Действия

Действия реализованы в файле «.cpp». Чтобы создать новый токен, необходимо отправить действие create. Create принимает два параметра; эмитент и максимальное количество нового токена. issuer - единственный, кому разрешено увеличивать количество новых токенов. issuer не может выдавать больше максимального количества.

Первая строка кода просто требует авторизации самой учетной записи контракта. Это можно указать с помощью флага командной строки -p eosio.token при нажатии действия.

В следующих нескольких строках извлекается символ переданного ресурса maximum_supply и выполняется некоторая обработка ошибок. Если какой-либо из eosio_assert выйдет из строя, весь код будет отменен, и транзакция не будет помещена в цепочку блоков.

Таблица stat с именем statstable создается с использованием имени символа (символа токена) в качестве области действия. Код проверяет, существует ли уже токен. В противном случае он создает и сохраняет новый статус токена в цепочке блоков. Первый параметр _self в функции emplace означает, что этот контрактный аккаунт «eosio.token» будет платить за выделенное хранилище.

Обратите внимание, что символ supply сохраняется, поскольку он используется в качестве ключа для поиска строки таблицы, но количество запасов еще не выдано.

Теперь вы можете выполнить следующее действие, проблема. Выдача будет иметь учетную запись, которая получит выпущенные токены, количество выпущенных токенов и памятку. Действие задачи выполняет два действия в одном, поскольку оно изменяет поставку созданных токенов и вызывает действие передачи для отправки выпущенных токенов. Опять же, первые несколько строк извлекают символ токена и выполняют проверку ошибок.

В следующем разделе кода будет создана таблица stat, используя имя символа в качестве области видимости. Он используется в качестве ключа для поиска токена, который был создан ранее с помощью действия create.

Обратите внимание, что existing currency_stat, возвращаемый из statstable.find(), является итератором, который указывает на найденный объект. Для краткости объявляется новая переменная с именем st, которой присваивается фактический объект, на который указывает итератор existing. Это позволяет нам использовать оператор . для доступа к переменным-членам вместо обозначения указателя ->.

issuer для созданного токена требуется для подписания этой транзакции, и выполняется дополнительная обработка ошибок.

Наконец, currency_stats st для нашего существующего токена изменяется, а выпущенный quantity добавляется к supply. У issuer этот supply также будет добавлен к их балансу, чтобы можно было отследить начальную поставку до их счета.

Сразу после этого через макрос SEND_INLINE_ACTION() вызывается функция transfer, которая переводит средства. Аргументы следующие:

  1. *this код контракта, которому принадлежит действие
  2. transfer начало действия
  3. {st.issuer, N(active)} разрешения, необходимые для действия
  4. {st.issuer, to, quantity, memo} аргументы в пользу самого действия

Это подводит нас к финальной передаче действия. Передача будет принимать четыре входных аргумента from, to, quantity и memo. from - это тот, кому будут отправлены жетоны, поэтому quantity будет вычтена из их баланса. to - это тот, кто будет получать жетоны, и поэтому quantity будет добавлен к их балансу. quantity - это количество отправленных токенов, а memo - это строка, которую вы можете отправить вместе с транзакцией. memo не используется и не хранится в рамках этого контракта.

Действие начинается с запроса разрешения учетных записей from и выполнения обработки ошибок для учетных записей from и to. Символ извлекается из quantity и используется для получения currency_stats для токена.

Функция require_recipient() уведомит отправителя и получателя о завершении действия.

Выполняется дополнительная обработка ошибок, и, наконец, вызываются две частные функции sub_balance() и add_balance(), чтобы вычесть баланс токена у отправителя и увеличить баланс токена для получателя.

Вот полный файл «eosio.token.cpp»

Примеры команд:

Табличные команды:

Примечание: эта статья была написана во время выпуска кода Dawn4.1.