Energia para um approve TRC-20 e outras chamadas de contrato na TRON
Energia é o que a TRON cobra para executar código de contrato, e uma transferência de USDT é uma chamada de contrato entre muitas. Um approve também a gasta, e o transferFrom que depois move os fundos aprovados também. Em 28 de outubro de 2026 rodamos os dois em dry-run no contrato do USDT: um approve levou 99,764 unidades de energia quando o allowance estava em zero e 33,764 quando já havia um definido, e um transferFrom levou 65,123 contra um allowance ilimitado e 89,325 contra um limitado. Chamadas a outros contratos têm valores próprios, e a energia alugada paga qualquer uma delas do jeito que paga uma transferência.
Uma delegação eleva o limite de energia da conta em que chega, e toda chamada de contrato que essa conta assina gasta desse limite antes de qualquer TRX ser queimado (o que é a energia da TRON). Nada numa delegação nomeia o contrato ou a função a que ela se destina. Uma chamada que não seja uma transferência difere no quanto gasta, que depende do contrato e da função que ela chama e do estado que encontra ali, e em alguns contratos no quanto disso quem assina paga.
O que as chamadas do USDT gastaram em dry-run
Um dry-run é uma chamada constante: um nó executa a chamada contra a sua própria cópia da cadeia, informa a energia que usou e descarta o resultado. Nada é assinado nem transmitido, e não custa nada. Fizemos os nossos por um nó completo público entre 08:29 e 08:34 UTC de 28 de outubro de 2026. Os donos eram contas reais, tiradas dos blocos mais novos logo depois de cada um ter aprovado um spender, e as retiradas foram rodadas em dry-run a partir desses spenders. O approve a partir de zero foi para um endereço que geramos para a nossa medição de setembro, que nenhum dono tinha aprovado. Lemos cada allowance e cada saldo momentos antes da chamada. Todos os valores abaixo vieram de uma chamada que teria dado certo. A transferência e as duas retiradas moveram uma unidade, um milionésimo de USDT, para o mesmo endereço, que tem USDT.
| Chamada do USDT, 28 de outubro de 2026 | Energia usada | Dela, informada como energy_penalty | Queimada a 100 sun por unidade |
|---|---|---|---|
transfer para um endereço que tem USDT | 64,285 | 49,635 | 6.4285 TRX |
approve, allowance em zero | 99,764 | 77,076 | 9.9764 TRX |
approve, allowance já definido | 33,764 | 26,076 | 3.3764 TRX |
transferFrom pelo spender, contra um allowance ilimitado | 65,123 | 50,281 | 6.5123 TRX |
transferFrom por outro spender, contra um allowance limitado | 89,325 | 68,976 | 8.9325 TRX |
Os dois tipos de approve vieram do mesmo dono para o mesmo valor novo. Um spender ainda não tinha allowance e o outro tinha um definido, e a chamada do primeiro custou 66,000 unidades a mais. É a mesma diferença que há entre uma transferência para um endereço sem USDT e uma para quem já tem, que medimos em setembro em 130,285 e 64,285 (os dois valores da transferência). Nos dois pares, a chamada mais barata sobrescreveu um número que já estava lá e a mais cara escreveu sobre um zero.
A menos que o implantador do contrato tenha concordado em assumir parte dela, como o da JustLend DAO fez (abaixo), quem assina uma chamada paga a energia dela. Num fluxo em que um cliente aprova o contrato de um comerciante e o comerciante depois retira os fundos, o cliente paga cada approve, e quem assina a chamada que retira paga por ela: o transferFrom da tabela, mais o código do próprio contrato do comerciante quando a retirada roda dentro dele. As duas retiradas que conseguimos simular diferiam no allowance. Com um ilimitado, o transferFrom do spender deu 838 unidades a mais que uma transferência simples do mesmo valor para o mesmo endereço, e com um limitado custou 24,202 acima disso. É um par de cada, e os pares tinham também donos e spenders diferentes.
Um pouco mais de três quartos de cada valor está num campo que o nó chama de energy_penalty, e a parcela é a mesma nas cinco chamadas, tanto num approve quanto num transfer.
Um contrato de empréstimo: as duas chamadas da JustLend DAO
Alugar energia da JustLend DAO é, em si, um par de chamadas de contrato, uma que abre a posição e outra que a devolve (quanto custa esse aluguel). Pareamos 30 aluguéis com as devoluções deles a partir do registro público do contrato nas 24 horas que terminaram na noite de 2 de setembro de 2026, e lemos o que cada chamada usou, no total, pelo recibo dela.
| Chamada da JustLend DAO, 2 de setembro de 2026 | Menos | Mediana | Mais |
|---|---|---|---|
Aluguel, rentResource | 52,672 | 69,306 | 84,290 |
Devolução, returnResource | 67,195 | 74,135 | 74,135 |
A tabela dá totais porque quem assina nem sempre paga tudo. O contrato está configurado para cobrar de quem o chama um décimo da energia e cobrir o resto com a energia do próprio implantador, até 90,000 unidades por chamada, enquanto essa energia durar. O nosso próprio aluguel naquela noite usou 84,290 unidades e quem o assinou pagou 8,429 delas. Menos de três horas antes, o aluguel de um terceiro pagou todas as 52,672 sozinho, porque a energia do implantador tinha acabado, e a devolução dele doze segundos depois pagou 62,200 de 74,135. Um dry-run informa o que uma chamada usa, enquanto quem assina paga qualquer valor desde o décimo que o contrato cobra de quem o chama até tudo, conforme a energia do implantador naquele segundo, então dimensione a chamada para tudo.
Dimensionando uma chamada que ninguém mediu para você
Nenhuma tabela cobre todos os contratos, e os valores acima se mexem com o estado que uma chamada encontra. O número em que confiar é um dry-run daquela chamada exata, a partir da conta que vai assiná-la, feito pouco antes de ela ser enviada. Qualquer nó completo responde a isso:
POST /wallet/triggerconstantcontract
{"owner_address": "T… (a conta que vai assinar)",
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"function_selector": "approve(address,uint256)",
"parameter": "… (os argumentos, codificados em ABI)",
"visible": true}
Confira a resposta antes de aceitar o número, porque uma chamada que reverteria ainda informa energia. Duas das nossas primeiras tentativas de transferFrom foram para pares que já não podiam pagar: um allowance tinha sido consumido nos segundos antes de perguntarmos, e um dono não tinha USDT nenhum. Voltaram com 5,947 e 4,845 unidades por um trabalho que termina em falha. O result.result deles ainda dizia true. O que as diferenciava era FAILED em transaction.ret, onde uma chamada que dá certo deixa uma entrada vazia.
Deixe folga acima do valor, já que um allowance pode ser gasto e um destinatário, esvaziado entre o dry-run e o bloco. Nós também deixamos folga do nosso lado: os nossos valores padrão de transferência, 65,000 e 131,000, ficam 715 unidades acima do que as duas transferências medem, e quando uma transferência de USDT assinada que nos é entregue no mode B dá, no dry-run, mais do que uma transferência a um endereço vazio mede, compramos a medição mais uma margem e julgamos a entrega contra a própria medição.
Defina o fee_limit da transação para cobrir o valor inteiro ao preço da rede de 100 sun por unidade, mesmo quando a energia é alugada. Um nó limita uma chamada ao seu fee_limit dividido pelo preço da energia e conta a energia delegada dentro desse teto, então um limite baixo interrompe uma chamada que tem na conta cada unidade de que precisa. O bandwidth é um medidor à parte: toda chamada também paga pelos seus bytes, e a energia não os cobre (energia e bandwidth).
Um swap por um contrato de exchange é a mesma aritmética com mais um contrato no meio: um approve que deixa a exchange mover os tokens, e depois a chamada à exchange. Não rodamos nenhum em dry-run.
Alugando energia para uma chamada por unidade
Os nossos mode A e mode B são construídos em torno de uma transferência de USDT, e o mode B aceita uma transfer de USDT assinada e nada mais. No mode A, quando o destinatário de uma transferência acaba sendo um contrato, rodamos o dry-run por você: o item volta como kind: custom, o energy_units dele é a medição, e um aviso contract_recipient diz o porquê (itens custom, antes de qualquer coisa ser assinada).
Para toda outra chamada há o mode C. Você nomeia a carteira e o volume, e nós delegamos a energia a essa carteira sem nenhum destinatário envolvido (o mode C no passo a passo da API). O volume pode ser energy_units, qualquer número inteiro de 65,000 a 50,000,000 por carteira, e o item volta como kind: bulk. O mode C não aceita custom, porque não há destinatário para nós simularmos, então a medição é sua. A carteira precisa estar ativada na cadeia, e um pedido para uma que não esteja volta recusado com inactive_wallet.
O aluguel de cinco minutos aceita volumes de até 131,000. Qualquer coisa maior tem de ir no aluguel de uma hora, e recusamos um volume desses no mais curto com bulk_needs_longer_lease: um volume grande é montado a partir de várias fontes e chega em pedaços com segundos de distância. Um approve a partir de zero cabe sob essa linha sozinho, com espaço para uma margem. Siga-o com uma transferência para quem já tem USDT e o par passa da linha, então vai na hora. O menor volume que vendemos cobre um approve sobre um allowance já definido com quase outro tanto de sobra.
POST /v1/estimate com o mesmo energy_units responde quanto esse volume seria cobrado neste momento e, em coverage, se o mercado o tem agora. Depois de entregue, o item fica em ready até send_before e então passa a expired, o que aqui quer dizer que o aluguel acabou: o fim normal. A cobrança é pela entrega, e a energia que a carteira deixa sem gastar volta com a delegação.
O que não medimos: um swap, uma chamada a qualquer contrato que não seja o USDT e a JustLend DAO, um transferFrom para um endereço sem USDT, e se esses valores se mantêm ao longo de semanas. Todo valor do USDT aqui é de uma chamada constante respondida por um nó; não enviamos nenhuma transação, então nenhum deles foi conferido contra um recibo.
Rode a chamada em dry-run, depois ponha esse volume na carteira que vai assiná-la: mode C e energy_units em POST /v1/orders →