O que quebra na sua integração se a TRON mudar o preço da Energy ou os parâmetros da rede

Na TRON, o preço da energy (getEnergyFee, atualmente 100 sun) e o teto de fee_limit (15,000 TRX) são parâmetros da rede alterados por propostas on-chain do comitê de SRs, sem necessidade de hard fork. Se estiverem fixados no código, qualquer mudança quebra a conversão de Energy para sun: o fee_limit fica baixo demais (as transações falham com OUT_OF_ENERGY) ou excessivo, e o seu cálculo de custo de transferência diverge da realidade. A solução é consultar wallet/getchainparameters e recalcular o orçamento antes de enviar.
Resposta curta
Na TRON, o preço da energy não é um gas ditado pelo mercado, mas um parâmetro da rede: getEnergyFee (parâmetro #11), atualmente 100 sun = 0.0001 TRX por unidade de Energy. Assim como o teto getMaxFeeLimit (15,000 TRX) ou o limite de CPU por transação (80 ms), ele é alterado pelo comitê de SRs por meio de uma proposta on-chain — sem hard fork, sem migração para um novo nó. Portanto, o que quebra na sua integração não é a assinatura nem o formato da transação, mas a aritmética do orçamento: a conversão de Energy para sun, o valor de fee_limit, as estimativas em cache e os cálculos de custo unitário. Tudo isso costuma estar embutido como constantes.
O parâmetro já mudou muitas vezes: diferentes versões da documentação da TRON mencionam 10, 100, 280 e 420 sun por unidade de Energy. Qualquer um desses números fixado no seu código produz uma discrepância de várias vezes.
O que exatamente deixa de funcionar
1. Um fee_limit fixado no código
Você recebe energy_required em Energy, mas passa fee_limit em sun: fee_limit (sun) = energy_required × getEnergyFee. Se o preço da energy subiu enquanto o seu multiplicador é uma constante, o orçamento fica curto: a transação é revertida com OUT_OF_ENERGY, e a Energy já consumida é cobrada e nunca reembolsada. Se o preço caiu, você simplesmente imobiliza TRX extra nas suas hot wallets. Outro clássico é a confusão de unidades: fee_limit = 100, pensado como "100 TRX", na prática autoriza 0.0001 TRX, e a chamada falha imediatamente. A documentação aponta explicitamente que fixar "15,000 TRX" e "100 sun" no código é um erro típico de produção.
2. Calculando o custo de uma transferência de USDT TRC-20
Uma transferência de USDT custa cerca de 64,000 de Energy se o destinatário tem saldo de tokens diferente de zero, e cerca de 130,000 de Energy se o saldo é zero (a diferença vem do custo do SSTORE quando um slot sai de zero). Você não pode multiplicar isso por um preço de energy constante: tanto o preço quanto o consumo mudam. A mainnet roda o Dynamic Energy Model — quando um limite de carga é excedido, o custo efetivo de Energy de um contrato popular é multiplicado por um fator de 1× a 4.4×, e o fator é recalculado a cada ciclo de manutenção (6 horas). O custo de opcodes individuais da TVM também foi objeto de votação — uma proposta assim apareceu na versão Cleobulus.
Conclusão: o custo de uma transferência é uma função de três variáveis (consumo, energy_factor, getEnergyFee), e não um número em uma tabela de preços.
3. Estimativas de energy em cache
O estimateenergy reflete o estado do nó no momento da requisição e não garante que a transação seguinte será bem-sucedida. Um cache que sobrevive ao ciclo de manutenção se torna inútil na virada do ciclo, junto com o energy_factor, e uma mudança no estado do contrato ou nos parâmetros da chamada o invalida ainda mais cedo. Os números da Shasta não valem para produção: a mesma chamada pode custar 31,000 de Energy na testnet e 90,000 na Mainnet.
4. Parâmetros do lado do contrato
Esses não são parâmetros da rede, mas quebram a sua economia com a mesma discrição. consume_user_resource_percent é a parcela do custo paga por quem chama; o implantador pode alterá-la após o deploy via wallet/updatesetting, e o novo valor se aplica a todas as chamadas seguintes. Se o implantador ficar sem Energy em staking, a parcela não paga passa silenciosamente a ser coberta pela queima do TRX do usuário. origin_energy_limit fica no registro on-chain do contrato: após UpdateEnergyLimitContract, todo chamador assume o novo valor a partir do bloco seguinte, sem perceber a mudança.
5. Fork gates e o limite de 80 ms
Novos recursos da TVM são habilitados por gates de parâmetros da rede; enquanto um gate não é ativado, o opcode correspondente é tratado como ILLEGAL_OPERATION, e o lançamento na Mainnet, na Nile e na Shasta é independente. O limite getMaxCpuTimeOfOneTx (80 ms, parâmetro #13) também é alterado por votação: excedê-lo resulta em OUT_OF_TIME e todo o fee_limit é cobrado. Se a complexidade da sua chamada estiver perto do limite crítico, ela falhará de forma intermitente.
O que mudar do seu lado
| Onde | O que fazer |
|---|---|
| Config | Remova as constantes energyPrice e maxFeeLimit; leia wallet/getchainparameters na inicialização e periodicamente |
| Cálculo do fee_limit | energy_required × getEnergyFee + uma margem para o DEM (até 4.4×), ou um orçamento conservador baseado no fator máximo |
| Estimativa | Reestime logo antes de enviar; não reutilize um cache na virada do ciclo de 6 horas |
| Tratamento de erros | Separe OUT_OF_ENERGY (orçamento insuficiente) de OUT_OF_TIME (limite integral cobrado) — a lógica de nova tentativa é diferente para cada um |
| Custo unitário | Calcule a partir do consumo real no recibo da transação, e não de uma lista de preços; considere o cenário "destinatário com saldo zero de USDT" |
O histórico de preços da energy está disponível em wallet/getenergyprices, e a lista de IDs de parâmetros e seus valores atuais está no glossário.
Conclusão
A TRON não tem EIP-1559 nem priority fees: todos pagam a mesma tarifa, e é justamente por isso que ela é alterada por uma proposta do comitê. Uma integração que lê os parâmetros da rede diretamente da cadeia e calcula seu orçamento dinamicamente sobrevive a uma mudança dessas sem um novo deploy. Uma integração construída sobre constantes descobre a mudança por meio de uma onda de erros OUT_OF_ENERGY e de uma discrepância no seu relatório de custos.