Перевод многие ко многим в Solana
Как работают парные переводы в Solana: одна транзакция на строку, 0,001 SOL за перевод и правило ренты, которое пропускает строку вместо того, чтобы её урезать.

Есть три способа разослать много платежей за один раз в Solana, и их постоянно путают. Мульти-сендер платит списку из одного кошелька. Коллектор собирает много кошельков в один. А потом идёт случай, который ни один из двух выразить не умеет.
Третья форма, перевод многие ко многим solana, держит каждого отправителя с его собственным получателем. Кошелёк 7 платит адресу 7, кошелёк 8 платит адресу 8, и строки никак не связаны друг с другом.
Звучит как мелочь. Это разница между одним источником и сорока независимыми источниками.
- Строка это одна транзакция. Кошелёк-отправитель этой строки платит всё, что на ней стоит.
- Комиссия платформы 0,001 SOL за перевод, сетевая комиссия 0,000005 SOL.
- Получатель, который никогда не держал этот токен, добавляет 0,00149 SOL рентного депозита.
- Строки, которые не проходят, пропускаются, а не урезаются.
Три формы массового перевода
Инструмент массовой рассылки это один ко многим. Один кошелёк, список получателей, один плательщик. Такая форма нужна для airdrop.
Пакетный сборщик средств это многие к одному. Двадцать кошельков, одна цель, и в конце всё лежит в одном месте.
Инструмент многие ко многим это третья форма и единственная, которая знает пары. У первой строки свой источник, у второй другой. Общей кассы нет, и строки друг друга не покрывают.
Сколько стоит одна строка
На строке могут стоять три позиции, и кошелёк-отправитель этой строки платит все три. Общего финансирующего счёта нет, поэтому кошелёк, который не покрывает свою строку, ничего не занимает у строки выше. Сетевая позиция это базовая комиссия в 5 000 лампортов за подпись, которую разбирает собственная документация Solana по комиссиям.
| Позиция | Режим SOL | Режим токена |
|---|---|---|
| Комиссия платформы | 0,001 SOL | 0,001 SOL |
| Сетевая комиссия | 0,000005 SOL | 0,000005 SOL |
| Токен-аккаунт получателя | не применяется | 0,00149 SOL, и только если этот получатель никогда не держал этот токен |
Третью строку стоит прочитать дважды, потому что именно она застаёт людей врасплох. Отправить SPL-токен на адрес, который его никогда не касался, значит создать аккаунт под этот токен, и Solana берёт за такой аккаунт рентный депозит. Депозит во много раз больше сетевой комиссии.
На сотне свежих получателей на депозиты уйдёт около 0,149 SOL, тогда как комиссия платформы составит 0,1 SOL. Депозит не сжигается: он лежит в токен-аккаунте получателя и возвращается тому, кто позже этот аккаунт закроет.
Строки, которые пропускаются
До подписи идут две проверки, и обе останавливают строку, а не меняют её.
Первая это простая арифметика. Если кошелёк-отправитель не покрывает свою сумму плюс комиссии плюс возможный токен-аккаунт, строка помечается и остаётся нетронутой. Ничего наполовину не уходит.
Вторая страннее, и её стоит понять, потому что в первый раз она выглядит как ошибка. Solana не разрешает оставить аккаунт с балансом выше нуля, но ниже рентного минимума. Для обычного кошелька этот минимум равен 0,00065 SOL, и он выводится по формуле из документации Solana по аккаунтам.
Опустошить аккаунт полностью можно. Оставить в нём 0,00005 SOL нельзя. Строка, которая загоняет кошелёк в эту щель, помечается как rent dust и остаётся неотправленной.
Почему нельзя просто урезать сумму
Можно было бы срезать сумму, пока она не влезет, но это хуже. Вы набрали число. Инструмент, который молча отправляет другое число, это инструмент, с которым потом не сойдётся ни одна таблица.
Отправьте весь баланс или снизьте сумму так, чтобы остаток прошёл минимум. Предпросмотр заранее показывает, какие строки затронуты, а инструмент опрашивает все аккаунты назначения одним вызовом, прежде чем что-либо подписать, поэтому смета, которую вы видите, совпадает с тем, что вы заплатите.
Одна транзакция на строку и почему это важно
Поскольку каждая строка это отдельная транзакция, упавшая строка падает одна. В пакете, где всё сложено в одну транзакцию, ошибка на тридцатой строке уносит двадцать девять предыдущих.
Раздельные транзакции стоят по 0,000005 SOL за строку, и именно эту часть счёта оптимизировать не стоит. Взамен получается результат, который читается построчно: сбой это одна строка в таблице результатов с причиной, и перезапускать нужно только её. Если важно, с какой скоростью транзакции проходят, цифры есть в разборе приоритетной комиссии Solana.
Когда нужен перевод многие ко многим в Solana
Для большинства людей главный случай это ротация кошельков. У вас есть набор кошельков с историей, которую хочется оставить позади, вы делаете свежий набор через генератор кошельков пачками, и хотите, чтобы старый кошелёк 7 профинансировал новый кошелёк 7 и ничего больше.
Второй случай это выплатный список, где плательщик меняется от строки к строке. Несколько проектов, несколько касс, одна таблица. Мульти-сендер не может это выразить вовсе, потому что источник у него ровно один.
Третий это перераспределение после снапшота, где каждому держателю платят с уже закреплённого за ним кошелька. Как прочитать это распределение до раздачи, написано в разборе распределения держателей токена.
Как подготовить список
Сделайте первый проход на двух строках. Таблица результатов скажет, во сколько строка обошлась на самом деле, вместе с депозитами токен-аккаунтов, до того как вы отправите весь список.
Проверьте также, держат ли получатели этот токен уже сейчас. В списке, наполовину состоящем из существующих держателей, позиция депозитов уменьшается вдвое, а на сотне строк это самая крупная цифра всего счёта.
И запишите заранее, какой кошелёк платит какую строку. После прохода это соответствие восстанавливается тяжелее, чем кажется сейчас, особенно если отправители только что созданы и ещё не имеют истории, по которой их различают.
Последнее про баланс: оставьте в каждом отправителе немного сверх его суммы. Баланс, подогнанный до последнего лампорта, может привести к тому, что строку пометят как rent dust и она не уйдёт, а докладывать SOL и запускать её заново дольше, чем сразу оставить запас.
Что меняется, когда список растёт
На десяти строках всё это удобная теория. На двух тысячах настоящей работой становятся две вещи, и обе происходят вне инструмента.
Первая это финансирование. Каждому отправителю нужна его сумма плюс комиссии ещё до старта, и никакая строка не может закрыть другую. Значит, сначала нужно раздать SOL отправителям, обычно из одной кассы, и делать это лучше с запасом, а не впритык.
Вторая это сверка после. На сорока строках достаточно посмотреть таблицу. На двух тысячах результат хочется выгрузить и сверить с исходным листом построчно, потому что пропущенные строки в обозревателе не появятся вовсе: как транзакции они не существуют.
Частые вопросы о парном переводе
Чем это отличается от нескольких запусков мульти-сендера?
У мульти-сендера ровно один источник за запуск. Сорок источников это сорок запусков и сорок ручных смен кошелька. Здесь один запуск и сорок строк.
Стоит ли чего-нибудь упавшая строка?
Зависит от того, где она упала. Строка, не прошедшая проверку до подписи, ничего не стоит: в сеть её транзакция не уходила. Если строка подписана, отправлена и упала уже в сети, она платит сетевую комиссию, как любая упавшая транзакция Solana. Комиссия платформы идёт инструкцией внутри той же транзакции, поэтому без успешного перевода она не списывается.
Могут ли отправители и получатели пересекаться?
Могут. Кошелёк вправе отправлять в одной строке и получать в другой. Строки идут независимыми транзакциями, и порядок между ними не гарантирован, поэтому если строка 2 тратит то, что приносит строка 1, разделите их на два запуска.
Почему моя строка помечена как rent dust?
Потому что остаток в кошельке-отправителе оказался бы между нулём и 0,00065 SOL. Отправьте весь баланс или снизьте сумму.
Нужен ли SOL в кошельке, который шлёт только токены?
Нужен. Сетевая и платформенная комиссии платятся в SOL, даже когда переводится токен.
Есть ли предел числа пар?
Фиксированного максимума нет, и ничто не мешает вставить тысячи пар. Пары подписываются и отправляются пачками по сто, а подтверждаются партиями до 256, и на каждое ожидание подтверждения отводится не больше 90 секунд, поэтому длинный запуск занимает несколько минут, а не секунд. На практике вас скорее ограничивает подготовка: каждый кошелёк-отправитель нужно профинансировать заранее. Запуск, за которым можно следить, можно и исправить, поэтому очень длинный список удобнее разбить на несколько запусков поменьше.
Как решить в одну строку
Если в вашей таблице есть колонка плательщика, вам нужна именно эта форма. Если все строки уходят с одного кошелька, берите мульти-сендер и запускайте его один раз вместо сорока. А если какая-то строка не ушла, сначала посмотрите на рентный минимум, прежде чем подозревать сбой. Про этот минимум есть отдельный разбор ренты в Solana и возврата SOL.


