Руководство для начинающих по TON: учетные записи, токены и безопасность

Фон

TON (The Open Network) — это децентрализованная блокчейн-платформа, изначально спроектированная и разработанная командой Telegram. Цель TON — создать высокопроизводительную и масштабируемую блокчейн-платформу для поддержки масштабных децентрализованных приложений (DApps) и смарт-контрактов.

Уникальность TON заключается в том, что она проста в использовании, глубоко интегрирована с Telegram, что позволяет обычным людям легко использовать токены. В то же время она сложна, имеет архитектуру, отличную от других блокчейнов, и использует неосновной язык смарт-контрактов FunC.

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

Характеристики TON

Генерация счетов

Метод генерации адреса учетной записи на TON отличается от большинства блокчейнов: это адрес смарт-контракта. Во-первых, все начинается с приватного ключа. Для генерации открытого ключа в TON в первую очередь используется алгоритм Ed25519, процесс которого выглядит следующим образом:

Существует две формы открытого ключа: первая — это необработанный открытый ключ, вычисленный из закрытого ключа, который выглядит следующим образом:

E39ECDA0A7B0C60A7107EC43967829DBE8BC356A49B9DFC6186B3EAC74B5477D

Другой — «улучшенный» открытый ключ, который содержит некоторую информацию и контрольные биты, и выглядит так:

Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2

Если вы думаете, что простое получение открытого ключа позволит вам узнать адрес счета, как в Ethereum, то вы ошибаетесь. Одного лишь наличия открытого ключа пользователя недостаточно, чтобы вычислить его адрес.

Как уже говорилось, адрес учетной записи пользователя является адресом смарт-контракта, но как можно развернуть смарт-контракт, не имея учетной записи?

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

Адрес пользователя также имеет несколько форм. Во-первых, это сырая форма, которая выглядит следующим образом:

0:b4c1b2ede12aa76f4a44353944258bcc8f99e9c7c474711a152c78b43218e296

Затем есть удобная форма, которая выглядит следующим образом:

Майннет:

  • Отказоустойчивость: EQC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0MhjilkPX
  • Неотклонимый: UQC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0Mhjilh4S

Testnet:

  • Отказоустойчивость: kQC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0Mhjilvhd
  • Неотклонимый: 0QC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0MhjilqWY

Внимательно изучив эти адреса, вы увидите, что они отличаются только первыми и последними символами, а средние account_id одинаковы.

Однако мы по-прежнему не видим связи между открытым ключом и адресом учетной записи.

Секрет кроется в строке initial data в начале, которая содержит открытый ключ пользователя, позволяющий ему управлять контрактом кошелька. Понять workchainId легко: TON — это не просто единая цепочка, а множество осколков.

Каждый шард — это часть всей сети, в которой обрабатываются определенные счета и транзакции. Чтобы найти смарт-контракты и управлять ими, необходимо указать, в каком шарде они находятся. В чем разница между Bounceable и Non-bounceable?

Это связано с тем, как смарт-контракты, но давайте продолжим разбираться дальше.

Контракт с кошельком

Ниже приведен фрагмент исходного кода контракта пользовательского кошелька. Из него видно, что при получении сообщения от пользователя он считывает четыре параметра: stored_seqno, stored_subwallet, public_key и plugins:

wallet-v4-code.fc



() recv_external(slice in_msg) impure {

var signature = in_msg~load_bits(512);

var cs = in_msg;

var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32));

throw_if(36, valid_until <= now());

var ds = get_data().begin_parse();

var (stored_seqno, stored_subwallet, public_key, plugins) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256), ds~load_dict()); ;;##The Initial Data

ds.end_parse();

throw_unless(33, msg_seqno == stored_seqno);

throw_unless(34, subwallet_id == stored_subwallet);

throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key));

//...

}

Действительно, когда этот контракт пользовательского кошелька развертывается, ему требуются некоторые начальные параметры, в том числе 256-битный public_key. Это гарантирует, что каждый пользователь будет иметь уникальный адрес контракта даже при использовании одного и того же кода контракта.

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

Развертывание разных контрактов кошелька или использование разных инициализационных данных приведет к тому, что адреса контрактов будут совершенно разными.

Жетон Джеттона

Токен представляет собой актив на блокчейне, что делает его фундаментальным элементом, который нам необходимо понять. Jetton — это стандартная форма токенов TON, состоящая из двух контрактов: Jetton-minter и Jetton-wallet.

При выпуске токена создается контракт Jetton-minter. При инициализации контракта записывается такая информация, как общее количество токенов, администратор, код кошелька и другие данные.

Когда токены распределяются среди пользователей, контракт Minter развертывает контракт кошелька для каждого пользователя. При инициализации контракта он записывает баланс пользователя, его права собственности, адрес контракта Minter, код кошелька пользователя и другую необходимую информацию. У каждого пользователя есть индивидуальный развернутый контракт.

Важно отметить, что созданный здесь контракт — это контракт кошелька для управления конкретными токенами Jetton, который отличается от контракта кошелька учетной записи пользователя. В качестве адреса owner_address здесь указан адрес кошелька учетной записи пользователя.

Когда пользователь Алиса передает токены пользователю Бобу, отношения вызова выглядят следующим образом:

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

Если во время операции остались остатки газа, они будут возвращены по соответствующему адресу, обычно это контракт на счет Алисы.

Ниже приведен пример передачи токена Jetton, разобранный браузером Tonviewer:

В то время как для передачи ERC20 требуется только одно обращение к контракту, передача токена Jetton требует как минимум четырех обращений к контракту. Этот метод разработан для обеспечения параллелизма на цепочке, что повышает эффективность транзакций.

Транзакции

Когда в аккаунте TON происходит определенное событие, оно запускает транзакцию. Наиболее распространенным событием является «получение сообщения». Транзакция включает в себя следующие элементы:

  • Входящее сообщение, которое первоначально запускает контракт (доступны специальные методы запуска).
  • Действия с контрактом в результате входящего сообщения, например, обновление хранилища контракта (необязательно).
  • Исходящие сообщения, отправленные другим участникам (необязательно).

Существует несколько ключевых особенностей, о которых следует знать при совершении сделок:

  1. Асинхронный: транзакций TON не завершаются за один вызов; они могут потребовать передачи сообщений нескольким различным смарт-контрактам для выполнения серии вызовов. Из-за разной маршрутизации в разделенных цепочках TON не может гарантировать порядок доставки сообщений между несколькими смарт-контрактами.
  2. Гонорары: Асинхронный характер транзакций создает трудности при оценке потребляемых комиссий. Поэтому кошельки часто отправляют немного дополнительных токенов в качестве платы при инициировании транзакции. Если вызываемый контракт имеет хороший механизм обработки комиссий, оставшиеся комиссии будут возвращены на кошелек пользователя. Пользователи могут заметить, что количество токенов в их кошельках внезапно уменьшается, а затем снова увеличивается через несколько минут, что связано с этим механизмом.
  3. Отскок: Bounce — это механизм обработки ошибок в контрактах. Если вызываемый контракт не существует или выдает ошибку, а транзакция задана как bounceable, вызывающему контракту будет возвращено сообщение bounced. Например, если пользователь инициирует перевод средств и в процессе происходит ошибка, сообщение об отказе необходимо для того, чтобы контракт кошелька пользователя смог восстановить свой баланс. Почти все внутренние сообщения, отправляемые между смарт-контрактами, должны быть отскакивающими, то есть у них должен быть установлен бит «bounce».

Безопасность активов

В TON есть множество функций, которые могут привести к проблемам с безопасностью, поэтому пользователям необходимо знать о некоторых распространенных «подводных камнях».

Атака на удержание гонорара

Как уже говорилось, кошелькам часто приходится отправлять небольшую дополнительную комиссию, чтобы предотвратить сбой транзакции, что дает возможность злоумышленникам. Если вы являетесь пользователем кошелька TON, вы могли столкнуться с ситуацией, когда ваш кошелек часто получает различные NFT или токены.

Поначалу они могут показаться мусорными токенами, но, проверив детали транзакции, вы обнаружите, что их можно продать за значительную сумму денег. Однако, когда вы пытаетесь инициировать транзакцию, вы замечаете, что требуемая комиссия чрезвычайно высока (1 TON). На этом этапе вам следует проявить осторожность, так как это может быть мошенничество с комиссией.

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

Фишинг с использованием первых и последних цифр

Фишинг первых и последних цифр не является уникальным для TON; эта фишинговая атака существует на многих крупных блокчейнах. Злоумышленники генерируют поддельную учетную запись для каждого адреса пользователя в сети с одинаковыми первыми и последними цифрами.

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

Фишинг в комментариях

При переводе токенов на TON пользователи могут добавить комментарий, чтобы аннотировать транзакцию. Эта функция часто используется при внесении депозитов на биржах, где биржи обычно требуют, чтобы пользователи указывали свой идентификатор пользователя в комментарии к депозиту. Однако эта функция часто используется злоумышленниками, которые пишут в комментариях мошенническую информацию, чтобы украсть активы пользователей. Например:

Пользователи должны быть особенно осторожны с NFT «Анонимный номер Telegram». Если пользователь активирует свой аккаунт Telegram с анонимным номером Telegram, но не включит функцию двухэтапной верификации, и этот NFT будет подделан, хакер сможет напрямую войти в целевой аккаунт Telegram и продолжить последующую кражу активов и мошеннические действия.

Уязвимости смарт-контрактов

Уязвимости в безопасности смарт-контрактов могут привести к потере средств, хранящихся в контракте. Пользователям следует выбирать проекты, прошедшие тщательный аудит. Смарт-контракты TON в основном программируются на языке FunC, хотя некоторые используют более продвинутый Tact или более низкоуровневый Fift.

Все эти языки очень оригинальны. Новые языки программирования влекут за собой новые риски безопасности, особенно для разработчиков, которым необходимо практиковать безопасное кодирование, осваивать лучшие практики безопасности и проходить тщательный аудит безопасности перед развертыванием в производственной среде. Из-за ограниченности объема в этой статье не будет подробно обсуждаться безопасность контрактов.

Атака на фальшивые депозиты

Пользователи кошельков и обменников должны быть осведомлены об атаках на фальшивые депозиты, которые обычно происходят в двух формах:

  1. Поддельные жетоны: Злоумышленник выпускает токен с метаданными, идентичными целевому токену. Если программа автоматического пополнения счета не проверит, что токен принадлежит правильному контракту майнера, это может привести к неправильному пополнению счета.
  2. Отскок: Процесс перевода средств в TON требует наличия отношений вызова между контрактами кошельков двух пользователей. Если контракт кошелька получателя не существует, а транзакция установлена как «отбойная», то сообщение будет отбито, а исходные средства за вычетом комиссии будут возвращены отправителю. Те, кого интересуют подробности, могут обратиться к нашей предыдущей статье о фальшивых депозитах.

Заключение

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