Вт. Июл 27th, 2021
    Smart Contracts, Free TON

    Автор статьи — Руслан Дорофеев. Источник Хабр.

    Перед тем как мы начнем писать свой токен, а затем систему смарт-контрактов, давайте проведем краткий обзор важных элементов смарт-контрактов для Free TON.

    В предыдущей статье Hello Word смарт-контракт для Free TON мы рассмотрели начальный этап работы со смарт-контрактами Free TON и HelloWorld.

    Структура статьи:

    1. Типы чисел int и uint, pure-функции и event (события): пишем калькулятор на blockchain;
    2. Структуры и массивы: смарт-контракты как база данных;
    3. Хеш-таблицы: mapping;
    4. Публичные ключи и require.

    В коде далее в начале функций будет присутствовать вызов tvm.accept(); поскольку мы рассматриваем учебные варианты смарт-контрактов.

    Калькулятор

    Объявить переменную с числовым типом можно с помощью int (целое число со знаком) и uint (целое без знака). Можно прописать количество бит для числа в суффиксе указанного числового типа, например: int8, int16, uint128. Типы int и uint — это тоже что и int256 и uint256. Над числами в смарт-контракте мы производим арифметические операции.

    Теперь напишем смарт-контракт с калькулятором. Он имеет одну функцию calc, которая принимает 3 uint-параметра: 2 числа-операнда и число, обозначающее номер операции над переданными функциями операндами. У нашей функции calc присутствует модификатор pure, что говорит о том, что данная функция не использует данные смарт-контракта, а выполняет свои операции только с тем, что ей передано в аргументах.

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

    События (event) в смарт-контрактах используются весьма часто, нам это пригодилось для того, чтобы сообщить дополнительную информацию о том, что возвращаемый функцией результат 0 — не результат, а ошибка, связанная с тем, что передан неизвестный номер арифметического оператора.

    Структуры и массивы

    То, что мы объявляем в начале (как правило) смарт-контракта вне области функций, относится к области памяти, связанной со смарт-контрактом. А так как смарт-контракт в итоге загружен в blockchain, то данные смарт-контракта хранятся в blockchain как в базе данных. Напишем простой смарт-контракт для хранения данных в blockchain.

    Структура User в нашем контракте служит для хранения информации о пользователе и содержит 2 поля данных типа uint: вес и баланс юзера. Поскольку мы хотим хранить данные не об одном, а о многих юзерах, после объявления структуры мы объявили массив структур этого типа. Теперь мы можем добавлять в наш массив пользователей с помощью push, а затем, вычислив по индексу массива идентификатор нового юзера, возвращаем его в событии NewUser.

    Обратите внимание на то, как выглядит возврат значений функцией GetUser: в данном случае мы объявляем переменные в returns, которым в теле функции присваиваем значения. Отметьте для себя, что модификатор pure мы поменяли на view.

    Хеш-таблицы: mapping

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

    Давайте добавим такой mapping в наш немного переделанный пример:

    Публичные ключи и require

    Вызов функции смарт-контракта похож на отправку сообщения: мы отправляем на адрес аккаунта со смарт-контрактом объект, содержащий название вызываемой функции и параметры для нее, если они требуются. Помимо этого в сообщение могут быть включены дополнительные данные: публичный ключ, подпись, значение value для передачи токенов TON Crystal в вызываемый аккаунт. Поговорим о публичном ключе.

    Получить значение публичного ключа аккаунта отправившего сообщение нашему смарт-контракту можно путем вызова API функции msg.pubkey(). В функции NewToken() мы выполнили присваивание accounts[tokens.length-1] = msg.pubkey();, в котором для каждого вновь создаваемого ID токена в отображение accounts помещается публичный ключ создавшего этот токен аккаунта, а в качестве ключа мы используем идентификатор этого токена, который вычисляем после пополнения массива tokens. Затем в SetTokenInfo(), где мы можем настроить название и символ для нашего токена, мы задаем требование, только при выполнении которого возможно продолжение вызова функции. Мы берем публичный ключ отправителя по значению tid, находим в отображении accounts, установленный при создании публичный ключ, сравниваем. Только если они равны, мы сможем установить или изменить имя и символ токена.

    7
    0