Как работает делегация энергии TRON
Делегация энергии TRON — это одна транзакция и два поля счёта. Адрес, застейкавший TRX под энергию, вызывает delegateResource, называя получателя, и с этого блока получатель тратит энергию, которую сам не стейкал, а у одолжившего остаются все замороженные им TRX. Ничего не переводится, на принимающей стороне ничего не одобряется, ключ никому не передаётся. На этом механизме стоит весь рынок аренды энергии, а всё дальнейшее прочитано из актуаторов самого java-tron, из живых чтений основной сети и из двух транзакционных прогонов в тестовой сети Nile 3 и 4 сентября 2026 года.
Что переходит, а что остаётся
Застейканные TRX не покидают счёт владельца: делегация лишь перекладывает их внутри счёта из одной корзины в другую — из баланса, замороженного под энергию, в делегированный под энергию. TRON Power, вес в голосовании, — это сумма обеих корзин, поэтому одалживание не стоит владельцу стейка ни голосов, ни наград за голосование. Счёт со стейкингом в основной сети, прочитанный 3 сентября 2026 года, показывает это лучше исходников: он подавал 3,080,000 голосов, держа неделегированным меньше половины этого, а остальное отдав в долг, и собственная цифра TRON Power у ноды для него была суммой обеих корзин.
Получателю достаётся вторая половина сделки: энергия и больше ничего. Поле, которое делегация пишет на принимающем счёте, в TRON Power не входит, поэтому одолженная энергия не приносит с собой голоса — у получателя в том же чтении цифры TRON Power не было вовсе, как не было её и у нашего счёта в Nile.
Что показывает принимающий счёт
Двигаются два числа. acquired_delegated_frozenV2_balance_for_energy растёт на делегированную сумму, и вместе с ним растёт лимит энергии счёта — на делегированные TRX, умноженные на сетевой TotalEnergyLimit и делённые на его TotalEnergyWeight, с отброшенной дробной частью. 3 сентября 2026 года принимающий счёт в основной сети, державший делегаций на 31246 TRX от двух делегирующих, показывал лимит энергии 299,638 — это ровно та же арифметика при отношении, которое сеть несла тем вечером: 180,000,000,000 против 18,770,236,993.
Здесь покупателей энергии и подстерегает сюрприз: делегация номинирована в TRX, а не в энергии. В знаменателе стоит общий вес стейкинга сети, он двигается каждый блок, и цифра, измеренная в другом месте, не переносится — тот же стейк на той неделе стоил в Nile примерно в 7.7 раза больше энергии, чем в основной сети.
Блокировка и четыре отказа
По умолчанию делегацию можно забрать обратно в любой момент. Помешать этому может lock=true в вызове делегации — и больше ничто. У неё один параметр, lock_period, считаемый блоками по три секунды: поле, которое читается как длительность, а на деле счётчик, — так что запрос на 300 таких блоков, сделанный ради 300 секунд, покупает пятнадцать минут, и молча. Оставленный нулём или опущенный, он означает 86,400 блоков — трое суток. Верхняя граница — параметр сети, и в основной сети 3 сентября 2026 года она стояла на 864,000 блоках, то есть тридцати сутках.
Блокировку можно продлить и нельзя сократить. Вторая делегация тому же получателю принимается, только если её срок не меньше оставшегося, и тогда она переставляет истечение всего накопленного баланса, а не одной новой части, — то есть пополнение заблокированной делегации заново блокирует всё, что под ней. Во всём остальном сеть отказывает. Эти четыре ответа пришли от ноды основной сети 3 сентября 2026 года по паре с живой суточной блокировкой; нода прогоняет собственную проверку актуатора уже при сборке любого из вызовов, поэтому все четыре — ответы самого актуатора, и ничего не было подписано и отправлено:
- блокировка на один блок поверх живой —
The lock period for ENERGY this time cannot be less than the remaining time[86241000ms] of the last lock period for ENERGY!, где названо оставшееся время, в миллисекундах; - блокировка на четыре часа поверх той же — тот же самый отказ. Проверяется не «дольше свежей блокировки», а «дольше того, что осталось»;
- блокировка на один блок выше потолка —
The lock period of delegate resource cannot be less than 0 and cannot exceed 864000!; - сам отзыв делегации —
insufficient delegateFrozenBalance(Energy), request=1000000, unlock_balance=0. Не «меньше, чем вы просили»: пока держится блокировка, заблокированный баланс не считается вовсе.
Проверенная сборка — ещё не блок, поэтому то же самое было проделано с блокировкой собственной. Два прогона в Nile 4 сентября 2026 года ставили блокировку, тут же просили отозвать делегацию, выжидали блокировку и просили снова: оба раза отказ той же последней фразой, символ в символ, и оба раза приём, как только истечение прошло, — на пяти минутах и на четырёх часах. Долгий прогон заодно решил, что именно считает единица: между двумя транзакциями часы заголовка ушли на 4,801 трёхсекундный слот, а высота блока — на 4,785, то есть шестнадцать слотов не дали блока, а блокировка всё равно отработала свои четыре часа. lock_period считает слоты блочных часов, а не произведённые блоки.
Как её закончить и как увидеть, что она кончилась
Делегирующий вызывает undelegateResource, и если блокировка не мешает, всё кончается за один блок. Ни один из двух вызовов не берёт платы сверх пропускной способности — оба актуатора оценивают себя в ноль, — и только поэтому энергию вообще можно продавать минутами. Против живой блокировки нет ни отмены, ни платы, которая купила бы выход; повторная делегация с lock=false выходом тоже не служит, потому что пишет отдельную строку и оставляет заблокированную стоять.
Блокировка видна ровно в одном месте: в строке делегации для этой пары, где expire_time_for_energy — отметка времени в миллисекундах. Отсутствие ключа означает, что блокировки нет, — так выглядит делегация обычного арендного поставщика, и строки одного пула в основной сети, прочитанные 3 сентября 2026 года, ключа истечения не несли вовсе. Это число надо читать, а не вычислять: актуатор ставит его по заголовку предыдущего блока, поэтому расчёт от блока самой делегации промахивается на один блок, а расчёт от отметки времени транзакции — каждый раз на разную величину. Оба прогона в Nile сошлись с сохранённым значением до миллисекунды по первому правилу и ни по одному из двух других.
Когда делегация кончается, два поля получателя не обнуляются — они исчезают из ответа, а строка делегации возвращается пустой. Всё, что опрашивает счёт, обязано считать отсутствие нулём, иначе будет и дальше показывать энергию, вернувшуюся к владельцу несколько минут назад.
Почему принимающий кошелёк ничего не подписывает
Всё это происходит на стороне делегирующего: получатель назван в транзакции, на его счёте пишется одно поле, и принимать, одобрять или подключать нечего — потому же делегация и не может дотянуться до того, что этот кошелёк держит. Два требования смотрят в другую сторону: адрес уже должен существовать как счёт и не должен быть контрактом — в этом актуатор отказывает наотрез. Именно поэтому энергию вообще можно арендовать по API (что такое энергия и откуда она берётся).
Что аренда достраивает сверху
Продавец энергии — это счёт со стейком и привычкой делегировать: он делегирует энергию вашему кошельку-отправителю на срок, вы тратите её на перевод USDT, а он забирает делегацию обратно. Сроки у продавцов разные; наш — 300 секунд, потому что перевод занимает секунды. В ответ на заказ приходит send_before — момент, когда закрывается окно доставки, за три секунды до конца этого срока, — и планировать надо по этому полю, а не по настенным часам.
Пока срок идёт, всё это видно, и в этом польза аренды на публичной сети: транзакция делегации на кошельке-отправителе, выросший на нём лимит энергии и строка между двумя адресами в любом обозревателе, который читает состояние делегаций. Энергия либо на адресе, либо нет, и платится за первое (сколько это стоит прямо сейчас). Кошелёк, отправляющий весь день, — тот же механизм по расписанию: правило Auto-refill доводит его обратно после каждого перевода, вместо того чтобы просить у вас заказ.
Двух вещей мы не измеряли, и обеим место здесь, в открытую. Первая — что делает собственный стейкинг принимающего счёта с делегацией, стоящей на нём: если получатель размораживает стейк или делегирует дальше посреди срока, код актуатора намекает, что там есть что найти, а мы этого не прогоняли. Вторая — пополнение: и исходники, и TIP-542 говорят, что принятая вторая делегация заново блокирует весь баланс под собой, а мы такого не проводили.