Я должен признать, что изучение эозио - это не прогулка по парку, и я понимаю, почему многие люди говорят, что у него крутая кривая обучения. Поскольку программное обеспечение eosio продолжает интенсивно и быстро развиваться, существует ограниченная документация и несколько рабочих примеров, на которые можно ссылаться. Я несколько раз попадал в тупик и хотел бы помочь улучшить опыт следующего разработчика, который придет. В этой статье я рассмотрю контракт «eosio.token», разбив его на отдельные части.
Откройте для себя и ознакомьтесь с лучшим программным обеспечением Blockchain
Что такое контракт eosio.token?
Контракт eosio.token позволяет создавать множество разных токенов. Это дает каждому возможность создавать и передавать токены. Каждый токен должен быть выпущен учетной записью «эмитента». Поскольку учетные записи могут включать в себя несколько сторон, вы можете использовать обычную учетную запись с владельцем и активными разрешениями или настраиваемую учетную запись для создания и управления токеном. Каждый токен относится к типу asset
и выглядит следующим образом:
1000000000.0000 SYS
1.0000 SYMBOL
0.10 SYS
asset
type - это число (которое, если я правильно помню, может достигать 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
, которая переводит средства. Аргументы следующие:
*this
код контракта, которому принадлежит действиеtransfer
начало действия{st.issuer, N(active)}
разрешения, необходимые для действия{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.