Токены SPL и токен-аккаунты в SSP

·8 мин. чтения·Автор: SSP Editorial Team
Обложка SSP Academy: токены SPL и токен-аккаунты в SSP

Токены SPL и токен-аккаунты в SSP

Если вы работали с токенами ERC-20 на Ethereum, модель токенов Solana покажется знакомой секунд на тридцать, а потом перестанет складываться. На Ethereum контракт токена ведёт реестр того, кто чем владеет, и ваш адрес значится в нём отдельной строкой. На Solana вашего адреса в записях токена нет вовсе. Вместо этого создаётся отдельный аккаунт, который хранит ваш баланс именно этого токена, — принадлежащий вам, но отличный от вашего основного адреса.

Одно это проектное решение объясняет почти все неожиданности, с которыми люди сталкиваются в токенах SPL: почему отправка токена новому человеку дороже, чем тому, кто уже им владеет; почему кошелёк может показывать нулевой баланс токена для адреса, который к нему никогда не прикасался; и почему десятичные знаки здесь важнее, чем где бы то ни было. Эта статья проходит по модели так, как её реализует SSP.

Экран сети Solana в боковой панели SSP Wallet, тёмная тема

Почему Solana нужен отдельный аккаунт на каждый токен

Базовое правило Solana: всё является аккаунтом, а у каждого аккаунта есть владелец, размер и рентный депозит, пропорциональный этому размеру. Здесь не бывает контракта, который тихо наращивает внутреннее отображение по мере прихода пользователей: хранилище обязано лежать в каком-то аккаунте, и кто-то должен за него платить.

Поэтому программа SPL Token делит работу. Аккаунт mint хранит факты о самом токене: общий выпуск, десятичные знаки и то, кто может эмитировать ещё. Каждый держатель получает собственный токен-аккаунт — небольшой аккаунт фиксированного размера, который записывает один баланс для одного mint и указывает владельца. Ваш баланс SOL живёт на вашем адресе; ваш баланс USDC живёт в токен-аккаунте, которым ваш адрес управляет.

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

Ассоциированный токен-аккаунт и кто за него платит

Если каждому держателю нужен токен-аккаунт, а создавать аккаунты может кто угодно, вы получили бы по нескольку токен-аккаунтов на человека и mint без способа понять, на какой отправлять. Ассоциированный токен-аккаунт — ATA — это соглашение, которое решает задачу: для данного владельца и данного mint существует один канонический адрес, детерминированно выведенный из обоих. Кошельки умеют его вычислять, поэтому публиковать его никому не нужно.

Загвоздка — рента. Токен-аккаунт занимает примерно 165 байт, что даёт около 0,002 SOL, удерживаемых как рентный депозит всё время существования аккаунта. Депозит возвращается при закрытии аккаунта, но внести его нужно заранее — и внести его должен тот, у кого есть SOL, чего у получателя самого первого в его жизни токен-перевода по определению может не быть.

SSP решает это так же, как любую другую комиссию в Solana. Когда вы отправляете токен SPL тому, чьего ATA не существует, транзакция включает идемпотентную инструкцию его создания, а ренту платит paymaster SSP. Ваше хранилище возмещает paymaster внутри той же транзакции — именно поэтому первый перевод новому получателю стоит примерно на 0,0025 SOL дороже повторного перевода тому же человеку. «Идемпотентная» — здесь ключевое слово: если аккаунт всё же уже существует, инструкция отрабатывает успешно и не делает ничего, вместо того чтобы обрушить весь перевод.

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

Что SSP поддерживает из коробки

SSP поставляется с нативным SOL, официальным mint USDC от Circle и FLUX на Solana. Любой другой токен SPL, обнаруженный в вашем хранилище, распознаётся и отображается рядом с ними.

Одно намеренное ограничение стоит назвать прямо: переводы Solana в SSP построены на классической программе SPL Token. Токены, выпущенные в рамках Token-2022 — более новой программы с transfer hooks, конфиденциальными переводами и прочими расширениями, — сегодня не входят в путь отправки. Это решение о границах, а не недосмотр: расширения Token-2022 способны менять то, что делает перевод, и поддержать их означает проверить каждое расширение на соответствие описанным ниже гарантиям декодирования на устройстве.

Как на самом деле собирается перевод токена

Когда вы отправляете токен SPL из SSP, подписываемая транзакция содержит по порядку:

  1. Создать ATA получателя, если нужно — идемпотентно, оплачивает paymaster, вне предложения.
  2. TransferChecked — переносит баланс с токен-аккаунта вашего хранилища на аккаунт получателя, с авторизацией от хранилища.
  3. Возместить paymaster — обычный перевод SOL из вашего хранилища, внутри предложения.

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

Аккаунт-источник — собственный ATA вашего хранилища, выведенный тем же детерминированным способом, где владельцем выступает программный адрес хранилища. Поскольку хранилище — это адрес, выведенный программой, а не пара ключей, вывод явно допускает владельца вне кривой ed25519. Если нужна подоплёка того, почему адрес хранилища устроен именно так, её разбирает материал самоинициирующаяся мультиподпись Solana.

Десятичные знаки — часть подписи

Вот здесь стоит сбавить темп, потому что именно тут токен способен вам солгать.

Mint объявляет, сколько десятичных знаков использует его токен. У USDC их шесть, у многих токенов — девять, единого правила нет. Если кошелёк показывает «100 USDC», но собирает перевод на количество сырых единиц, исходя из неверных десятичных знаков, вы можете отправить в тысячу раз больше и не увидеть на экране ничего подозрительного.

SSP использует TransferChecked вместо простой инструкции перевода. Разница в том, что TransferChecked встраивает адрес mint и байт десятичных знаков прямо в подписываемые данные инструкции. Отсюда следуют три отдельные проверки:

  • Ваше расширение декодирует байты и сверяет их с тем, что показывает.
  • SSP Key декодирует те же байты независимо на телефоне и сверяет их с метаданными токена, переданными расширением.
  • Ончейн-программа SPL Token сверяет десятичные знаки из инструкции с фактическими десятичными знаками mint и отклоняет транзакцию при расхождении.

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

Проверка отправки Solana в SSP Wallet, тёмная тема

Получение токенов

Получать проще, с одной тонкостью. Дайте отправителю адрес своего кошелька — тот, что SSP показывает на экране получения, — а не адрес токен-аккаунта. Что бы вам ни отправляли, нужный ATA выводится из вашего адреса и mint, и кошелёк отправителя создаёт его при необходимости.

Если ваше хранилище никогда не держало этот токен, аккаунт не будет существовать, пока не придёт первый перевод, а его ренту платит тот, кто вам отправляет. Это нормально и ничего от вас не требует. Зато это значит, что обозреватель блоков не покажет никакого токен-аккаунта для токена, который вам обещали, но ещё не прислали: это несуществующий пока аккаунт, а не потерянный перевод.

Частые ошибки

Отправка на адрес токен-аккаунта вместо адреса кошелька. Некоторые обозреватели выводят ATA на видное место. Отправить токен на токен-аккаунт вместо его владельца — хорошо известный способ потерять средства в Solana. SSP ожидает адрес кошелька владельца и выводит остальное сам.

Считать незнакомый токен безопасным потому, что он появился в кошельке. Создать mint и прислать его вам может кто угодно, а имена mint способны имитировать настоящие токены. Появление токена в хранилище — не рекомендация. Сверьте адрес mint с официальным источником, прежде чем считать баланс реальной ценностью.

Ожидать одобрений в духе Ethereum. У токенов SPL есть механизм делегата, но шаблон постоянного разрешения, из-за которого одобрения ERC-20 остаются повторяющимся риском, — не то, как построено большинство приложений Solana. Если вы пришли с Ethereum, одобрения токенов: разрешения, которые вы раздаёте снова и снова объясняет привычку, от которой вы отучаетесь, а Ethereum в SSP даёт сравнение.

Забыть про надбавку за первую отправку. Дополнительные ~0,0025 SOL при первом переводе новому получателю — это рента, а не комиссия, которую забирает SSP. Она лежит в токен-аккаунте получателя и возвращается ему, если он когда-нибудь его закроет.

Пошаговую механику реального перевода см. в материале отправка Solana через SSP. О том, как SSP держит само хранилище в мультиподписи 2-из-2 без создателя, начните с материала Solana в SSP.

Поделиться статьёй

Похожие статьи