Расширенные технические темы: Token-2022, PDA, Multisig и ошибки
Продвинутое руководство по техническим аспектам: провалы транзакций, специфика Token-2022, управление PDA-аккаунтами, интеграция аппаратных кошельков и интерпретация ошибок.
#Почему транзакции не проходят: технические причины
Даже правильно сформированная транзакция может не попасть в блок. Понимание причин помогает избежать потери времени и газа.
Архитектура транзакций в Solana
Каждая транзакция в Solana имеет жёсткие лимиты и временные ограничения:
- Максимальный размер: 1232 байта (MTU сетевого пакета)
- Compute Units лимит: 1,400,000 CU на транзакцию
- Время жизни: 150 слотов (~60-90 секунд)
- Blockhash validity: Действителен только для недавних блоков
Transaction Expired: самая частая ошибка
Что произошло:
Транзакция содержит ссылку на недавний blockhash (идентификатор блока). Если за время ожидания в очереди прошло больше 150 слотов, сеть отклоняет транзакцию как устаревшую.
Технический процесс:
- Вы формируете транзакцию с blockhash блока N
- Транзакция ждёт включения в блок
- Сеть достигла блока N+150
- Ваш blockhash больше не в списке "recent blockhashes"
- Валидаторы отклоняют транзакцию с ошибкой "Blockhash not found"
Почему это происходит:
Перегрузка сети: Во время популярных NFT-минтов или ажиотажа вокруг новых токенов сеть получает миллионы транзакций. Priority Fee определяет очерёдность.
Низкая Priority Fee: Если вы установили минимальную комиссию, валидаторы будут приоритезировать транзакции с более высокой платой.
RPC-проблемы: Публичные RPC-ноды могут быть медленными или терять соединение.
Решение:
- ✅ Увеличьте Priority Fee до "Medium" или "High" в настройках кошелька
- ✅ Повторите попытку через 1-2 минуты (blockhash обновится автоматически)
- ✅ Используйте приватные RPC-endpoint'ы (Helius, Triton) для стабильности
Важно: Expired-транзакция не списывает комиссию. Ваши средства в безопасности.
Account State Changed: конфликт данных
Что произошло: Между моментом формирования транзакции и её выполнением состояние аккаунта изменилось.
Типичные сценарии:
Сценарий 1: Пополнение во время cleanup
- Сканер определил: аккаунт пустой, баланс = 0
- Вы формируете транзакцию CloseAccount
- Кто-то присылает вам 1 токен на этот аккаунт
- Транзакция пытается закрыть аккаунт с балансом > 0
- Ошибка: "Account has non-zero balance"
Сценарий 2: Race condition с другой транзакцией
- Вы отправили swap токена А на DEX
- Одновременно отправили транзакцию закрытия аккаунта токена А
- Обе транзакции пытаются изменить один аккаунт
- Одна проходит, вторая отклоняется
Решение:
- ✅ Повторите сканирование - данные обновятся
- ✅ Используйте инструменты с pre-flight симуляцией (проверка перед отправкой)
- ✅ Избегайте одновременных операций с одним токеном
Compute Budget Exceeded: превышение вычислительного лимита
Что произошло: Транзакция пыталась выполнить слишком сложные операции, превысив лимит 1.4M Compute Units.
Причины:
- Слишком много инструкций в пакете: Попытка закрыть 30-40 аккаунтов за раз
- Сложные смарт-контракты: Некоторые Token-2022 с extensions требуют больше вычислений
- Nested программные вызовы: Программа А вызывает программу Б, которая вызывает С
Решение:
- ✅ Уменьшите количество аккаунтов в пакете (закрывайте по 15-20 вместо 25-30)
- ✅ Используйте инструменты, которые автоматически оптимизируют размер пакетов
- ✅ Добавьте инструкцию
ComputeBudgetProgram.setComputeUnitLimit()для увеличения лимита
Техническая деталь: Можно запросить до 1,400,000 CU, но это требует пропорционально большей Priority Fee:
Priority Fee = CU requested × Price per CU
Insufficient Lamports: недостаточно средств
Что произошло: На балансе не хватает SOL для выполнения операции.
Неочевидные причины:
Rent-exempt minimum: Если вы пытаетесь перевести весь SOL, но у вас открыты пустые аккаунты, кошелёк должен сохранить минимум для покрытия rent всех аккаунтов.
Динамическое изменение газа: В моменты перегрузки Priority Fee может вырасти в 10-100 раз. Транзакция, сформированная с расчётом на 0.000005 SOL газа, может потребовать 0.0005 SOL.
Множественные транзакции: Вы отправили 5 транзакций подряд, каждая резервирует газ. Последняя не проходит из-за нехватки свободных средств.
Решение:
- ✅ Всегда держите минимум 0.01-0.02 SOL на балансе
- ✅ Используйте "Advanced" режим в кошельке для контроля резервирования газа
- ✅ Отправляйте транзакции последовательно, дожидаясь подтверждения
#Работа с Token-2022: новый стандарт и его особенности
Token Extensions Program (Token-2022) - это эволюция классического SPL Token, запущенная в 2023 году.
Ключевые отличия от SPL Token
SPL Token (классический):
- Program ID:
TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA - Фиксированный размер: 165 байт
- Базовая функциональность: transfer, mint, burn, approve
Token-2022:
- Program ID:
TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb - Переменный размер: 165-500+ байт (зависит от extensions)
- Расширенная функциональность: 16+ дополнительных возможностей
Основные расширения (Extensions)
Transfer Fee Extension:
Позволяет создателю токена взимать комиссию при каждом переводе.
Пример:
Transfer 100 токенов
Fee: 2% = 2 токена
Получатель получает: 98 токенов
Создатель получает: 2 токена комиссии
Влияние на rent recovery: Аккаунты с Transfer Fee занимают больше места → rent увеличивается до ~0.0025 SOL.
Permanent Delegate:
Создатель токена назначает адрес, который может переводить токены с любого кошелька без согласия владельца.
Применение:
- Централизованные стейблкоины (USDC может заморозить средства преступников)
- Игровые токены (разработчик может конфисковать при бане)
Риск: Создатель имеет backdoor-доступ к вашим средствам.
Confidential Transfers:
Шифрование балансов с использованием zero-knowledge proofs.
Как работает:
- Публично виден только зашифрованный баланс
- Отправитель и получатель знают реальные суммы
- Валидаторы могут проверить корректность без раскрытия
Размер аккаунта: До 400 байт → rent до ~0.004 SOL
Non-Transferable Tokens:
Токены, которые нельзя передавать (soulbound).
Применение:
- Сертификаты и дипломы
- Достижения в играх
- KYC-токены (подтверждение личности)
Особенность rent recovery: Такие токены нельзя сжечь, но можно закрыть аккаунт, если создатель предусмотрел эту функцию.
Почему старые инструменты не видят Token-2022
Техническая причина:
Классические cleanup-сервисы используют RPC-метод, который возвращает только SPL-токены. Правильный подход требует двух отдельных запросов для SPL и Token-2022 программ.
Возврат rent за Token-2022
Суммы возврата (примерные):
- Базовый Token-2022: ~0.00204 SOL (как SPL)
- С одним extension: ~0.0025 SOL
- С двумя extensions: ~0.003 SOL
- С Confidential Transfers: ~0.004 SOL
Важно: Фактическая сумма зависит от точного размера аккаунта в байтах.
Процесс закрытия:
Идентичен SPL-токенам:
- Burn остатков (если есть)
- CloseAccount инструкция
- Rent возвращается на указанный адрес
Единственное отличие: Нужно использовать правильный Program ID при формировании инструкции.
#PDA-аккаунты и возврат rent из DeFi-протоколов
Program Derived Address (PDA) - это аккаунты, управляемые программами, а не пользователями.
Что такое PDA технически
Обычный аккаунт:
Private Key → Public Key (адрес)
Подпись транзакции = ваш приватный ключ
PDA:
Program ID + Seeds → Детерминированный адрес
Подпись транзакции = программа (через invoke_signed)
Ключевая особенность: PDA не имеет приватного ключа. Только программа может подписывать операции от его имени.
Где используются PDA
Lending протоколы (Solend, MarginFi):
Когда вы вносите депозит:
- Программа создаёт PDA для хранения ваших collateral
- Вы владелец, но не контролируете напрямую
- Вывод возможен только через функцию программы
withdraw()
DEX (Raydium, Orca):
Открытые ордера хранятся в PDA - Order Book содержит PDA каждого открытого ордера. Отмена ордера = закрытие PDA + возврат rent.
Staking программы:
Ваши застейканные токены лежат в PDA - программа контролирует unlock-период, вы не можете "украсть" свои же токены до истечения срока.
Можно ли вернуть rent из PDA
Зависит от реализации программы.
Если программа предусмотрела Close Authority для пользователя:
- ✅ Вы можете закрыть PDA и вернуть rent
- Примеры: Устаревшие версии Serum DEX, старые lending-протоколы
Если программа не предусмотрела:
- ❌ PDA останется открытым навсегда
- Примеры: Некоторые staking-программы создают PDA навсегда
Если средства всё ещё используются:
- ❌ Закрытие невозможно до вывода
- Пример: Нельзя закрыть PDA с активным займом в лендинге
Как определить, можете ли вы вернуть rent
Шаг 1: Проверка Owner
Откройте аккаунт в Solscan и проверьте, является ли Owner известной программой (Raydium, Orca).
Шаг 2: Проверка баланса
Если баланс = только rent (без токенов/данных), возможно закрытие.
Шаг 3: Проверка Close Authority
Некоторые explorers показывают поле Close Authority. Если это ваш адрес - вы можете закрыть.
Автоматическое определение в cleanup-инструментах
Качественные сервисы:
- Сканируют все аккаунты, где вы Rent Payer
- Фильтруют по программам с известной логикой
- Проверяют баланс и статус через RPC
- Показывают только безопасные для закрытия PDA
Предупреждение: Не закрывайте PDA вручную без понимания. Можно потерять доступ к средствам в протоколе.
#Работа с Ledger и аппаратными кошельками
Hardware wallets обеспечивают максимальную безопасность, но требуют дополнительных шагов при cleanup-операциях.
Почему Ledger блокирует сложные транзакции
Ограничение экрана: Ledger Nano S/X имеет экран 128×64 пикселя. Он может показать адрес получателя (частично), сумму перевода и базовую информацию о транзакции.
Что он НЕ может показать:
- Детали 20 инструкций CloseAccount
- Список всех затрагиваемых аккаунтов
- Сложные смарт-контракт вызовы
Защитный механизм: Если Ledger не может отобразить детали транзакции, он отклоняет её по умолчанию с ошибкой:
Condition of use not satisfied (0x6985)
Что такое Blind Signing
Blind Signing (Слепая подпись) - это режим, в котором вы разрешаете Ledger подписывать транзакции без полного отображения деталей на экране.
Как включить:
- Подключите Ledger к компьютеру
- Откройте приложение Solana на устройстве
- Нажмите обе кнопки одновременно для входа в Settings
- Найдите опцию "Blind signing"
- Переключите на "Enabled"
- Выйдите из Settings
Важно: Эта настройка находится внутри приложения Solana на Ledger, а не в Ledger Live на компьютере.
Риски Blind Signing
Потеря проверки на устройстве: Вы не видите, что подписываете. Теоретически вредоносный сайт может отправить транзакцию перевода всех средств, и вы не увидите этого на экране Ledger.
Как минимизировать риски:
- ✅ Включайте Blind Signing только для конкретной операции
- ✅ Используйте только проверенные сервисы
- ✅ Проверяйте симуляцию транзакции в кошельке Phantom/Solflare (если используете как интерфейс)
- ✅ Выключайте Blind Signing сразу после использования
Альтернативный workflow без Blind Signing
Метод 1: Частичная очистка
Некоторые простые операции не требуют Blind Signing - закрытие 1-3 аккаунтов за транзакцию, простые SPL-токены без extensions.
Метод 2: Экспорт через xpub
- Экспортируйте extended public key из Ledger
- Импортируйте в горячий кошелёк (watch-only)
- Сделайте cleanup на горячем кошельке
- Отправьте recovered SOL обратно на Ledger
Метод 3: Создание промежуточного кошелька
- Переведите средства на временный горячий кошелёк
- Сделайте cleanup на горячем кошельке
- Верните средства обратно на Ledger
#Multisig-кошельки и rent recovery
Multisignature wallets (Squads Protocol, Goki) используют несколько ключей для авторизации транзакций.
Как работает Multisig в Solana
Структура:
Multisig Vault (PDA)
├── Signer 1: Alice (1/3 голоса)
├── Signer 2: Bob (1/3 голоса)
└── Signer 3: Charlie (1/3 голоса)
Threshold: 2/3 (нужны подписи двух из трёх)
Процесс транзакции:
- Alice создаёт Proposal: "Закрыть 50 пустых аккаунтов"
- Bob просматривает и Approve
- Достигнут threshold (2/3) → транзакция выполняется автоматически
- Charlie может Approve позже (но это уже не нужно)
Почему обычные cleanup-инструменты не работают с Multisig
Проблема: Стандартные сервисы пытаются отправить транзакцию немедленно после подключения кошелька. Но в Multisig:
- Одна подпись недостаточна
- Нужно создать Proposal
- Дождаться других подписантов
Технический момент: Multisig Vault - это PDA. Токены хранятся не на адресах подписантов, а в Vault. Поэтому сканирование адреса Alice покажет 0 аккаунтов, хотя в Vault их сотни.
Workflow для Multisig cleanup
Шаг 1: Сканирование Vault-адреса
Узнайте адрес Multisig Vault в интерфейсе Squads, вставьте его в cleanup-сканер (Read-Only).
Шаг 2: Экспорт списка аккаунтов
Некоторые продвинутые инструменты позволяют экспортировать список аккаунтов для закрытия.
Шаг 3: Создание Proposal вручную
В интерфейсе Squads:
- New Proposal → Custom Instruction
- Program: Token Program / Token-2022 Program
- Instruction: CloseAccount
- Account list: вставить из экспорта
- Create Proposal
Шаг 4: Сбор подписей
Отправьте ссылку на Proposal другим подписантам. После достижения threshold транзакция выполнится.
Автоматизация для Multisig
Squads SDK: Разработчики могут создать скрипт для автоматического создания Proposal, сбора подписей и выполнения.
Стоимость: Газ за создание Proposal + газ за выполнение транзакции.
#Обработка ошибок: расшифровка кодов
Solana использует числовые коды ошибок, которые не всегда понятны пользователю.
Частые коды ошибок при cleanup
0x0 (Success):
Не ошибка. Транзакция выполнена успешно.
0x1 (Insufficient funds):
Недостаточно SOL для оплаты газа или rent-exempt minimum.
Решение: Пополнить баланс.
0x3 (Invalid account data):
Аккаунт имеет некорректную структуру данных.
Причина: Багнутый токен, повреждённые метаданные.
Решение: Пропустить этот аккаунт, закрыть остальные.
0x7 (Account already in use):
Другая транзакция одновременно модифицирует этот аккаунт.
Решение: Подождать 5-10 секунд, повторить.
0xBB8 (3000 - Account not rent exempt):
Попытка создать аккаунт без достаточного депозита.
В контексте cleanup: Баг инструмента (редкая ошибка).
0x1771 (6001 - Custom program error):
Ошибка, специфичная для конкретной программы. Нужно смотреть детали в error message.
Как получить детали ошибки
В Phantom/Solflare:
После неудачной транзакции появляется кнопка "View in Explorer". Кликните → откроется Solscan с полным логом.
В Solscan:
- Найдите секцию "Program Logs"
- Ищите строки с "Error:"
- Часто есть человекочитаемое описание
Пример:
Program log: Error: Account has non-zero balance
Program TokenkegQf... failed: custom program error: 0x10
Расшифровка: 0x10 = "Non-zero balance", нельзя закрыть аккаунт с токенами.