BchainPay logoBchainPay
EngineeringTRONUSDTStablecoinsInfrastructure

TRON energy model: zero-fee USDT transfers for crypto merchants

TRON charges bandwidth and energy for USDT transfers. Stake TRX, estimate resource costs, manage fee accounts, and cut TRC-20 payment fees to near zero.

By Cipher · Founding engineer, BchainPay8 min read
Illustration for TRON energy model: zero-fee USDT transfers for crypto merchants

The reason USDT on TRON dominates global stablecoin transfer volume isn't loyalty — it's fees. An EVM USDC transfer costs a dollar or more depending on gas. A TRON USDT transfer that hits a well-resourced address costs zero TRX. For merchants in emerging markets where customers are sending $30 to $200, that difference is the entire business case.

But "zero TRX" is not free: someone paid for it. TRON's resource model hides the fee inside a staking position. Understanding exactly how bandwidth and energy work, how to size a staking account for your transaction volume, and how to delegate resources to per-merchant deposit addresses is the difference between a 0.0% on-chain fee rate and an invisible 30% tax on every transaction.

Bandwidth versus energy#

Every transaction on TRON consumes two resources: bandwidth and energy.

Bandwidth maps to transaction size in bytes. A simple TRX transfer might consume 260 bytes; a TRC-20 USDT transfer, after encoding, is typically 350–400 bytes. TRON treats bandwidth like a renewable daily allowance: every account gets 600 free bandwidth units per day from the system. You can stake TRX to increase that cap. If your daily free allowance covers the tx size, bandwidth is effectively free. If it doesn't, 1 bandwidth unit costs 1,000 sun (0.001 TRX) from your balance.

Energy maps to virtual-machine execution cost. Plain TRX transfers have no contract execution and consume zero energy. TRC-20 transfers, however, call the USDT contract's transfer(address,uint256) function, and that call has a fixed VM execution cost regardless of network conditions: 65,000 energy for a standard USDT TRC-20 transfer (roughly 68,000 when the recipient is receiving USDT for the first time, because initializing a new storage slot costs extra).

Energy is not renewable on a per-day basis the way bandwidth is. You obtain it by staking TRX. If your account carries no staked energy, the 65,000 units are burned directly from your TRX balance at a dynamic price set by network demand. At 420 sun per energy unit — a rate we observed throughout early 2026 — that is 27.3 million sun, or 27.3 TRX per transfer. At a $0.12 TRX price, each unoptimized USDT transfer costs $3.28. On a $50 payment that is a 6.6% fee. Not zero.

Stake 2.0 and the energy formula#

TRON's Stake 2.0 model (live since November 2023) separates energy and bandwidth into independent staking pools. You lock TRX to obtain one specific resource type and receive TRON POWER (TP) as a governance token alongside the resource units.

The energy yield from staking is not fixed; it depends on total network-wide staking. The current ratio (April 2026) is roughly 1 TRX staked = ~290,000 energy per day. Energy regenerates: once consumed, it restores at 1/24 of your total daily limit per hour, fully recovering over 24 hours.

To size a staking account for your gateway:

  1. Measure your peak USDT transfer volume per day (example: 5,000 transfers).
  2. Multiply by energy per transfer with a 5% safety margin: 65,000 × 1.05 = ~68,250 energy per transfer.
  3. Total daily energy needed: 5,000 × 68,250 = 341,250,000 energy/day.
  4. At 290,000 energy per staked TRX per day: ~1,177 TRX staked covers 5,000 daily transfers.

At $0.12/TRX, 1,177 TRX is a $141 capital lock you hold as long as you want zero-fee transfers at that volume. The unstake period is 14 days, so treat this as a permanent float rather than operational liquidity.

Delegating energy to deposit addresses#

TRON's system contract supports delegateresource(owner, receiver, resource, amount). This is the mechanism that makes per-merchant deposit addresses practical: instead of funding each deposit address with enough TRX to cover its own fees, you hold a single resource account with the staking position and delegate a budget of energy to each deposit address when a payment intent is created.

Delegation is temporary by default (one locking period), but the duration is configurable. The key constraint: delegation is always account-to-account. There is no shared pool that any address can draw from automatically.

A practical pattern for a payment gateway:

  1. Maintain one resource account per high-volume merchant (shared for smaller merchants).
  2. When a payment intent is created, call delegateresource to assign 70,000 energy to the deposit address for a 72-hour window.
  3. After the payment is confirmed and swept, undelegate to recycle that energy to the next intent.
  4. Hold a 20% energy buffer above your measured peak to absorb burst volume — adding more staked energy requires an on-chain transaction that takes at least one block to confirm.

BchainPay handles steps 2 to 4 automatically when chain=tron is set on a payment intent and a resource account is configured on the merchant profile. If you are operating a hybrid setup, the BchainPay API exposes the full resource state.

Querying resource state#

The chain-resource endpoint returns the current energy balance and delegation schedule for the gateway's resource account:

curl -s https://api.bchainpay.com/v1/chains/tron/resources \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json"

Response:

{
  "chain": "tron",
  "resource_account": "TRxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "energy_limit":      341250000,
  "energy_used":        87420000,
  "energy_available":  253830000,
  "bandwidth_limit":         600,
  "bandwidth_used":          312,
  "delegations_active":      143,
  "staked_trx":           1177.0,
  "updated_at": "2026-04-27T10:41:00Z"
}

energy_available is energy_limit - energy_used, accounting for regeneration since the last top-up. The field delegations_active counts open delegation grants — each open grant consumes a small administrative slot in the resource account and contributes to the energy_used tally.

Creating a payment intent with automatic energy delegation#

When you create a TRC-20 payment intent via the BchainPay API, energy delegation happens before the deposit address is returned to the caller:

const res = await fetch(
  'https://api.bchainpay.com/v1/payment-intents',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.BCHAINPAY_SECRET_KEY}`,
      'Content-Type': 'application/json',
      'Idempotency-Key': intentId,
    },
    body: JSON.stringify({
      amount:   5000,       // $50.00
      currency: 'USDT',
      chain:    'tron',
      metadata: { order_id: 'ORD-8842' },
    }),
  },
);
const intent = await res.json();
// intent.deposit_address has had 70,000 energy delegated to it
// intent.resource_preflight.energy_delegated === 70000
// intent.resource_preflight.fee_trx === 0

When resource_preflight.fee_trx is non-zero, the resource account did not have sufficient energy to cover full delegation and the deposit address will burn TRX for the transfer fee. This is the signal to top up the staking balance before the next intent is created.

Monitoring and alerting thresholds#

Three metrics worth alerting on:

Energy utilization above 80%. At 80% consumed, new delegations start borrowing from the buffer. Set a critical alert at 80% to trigger a staking top-up before you hit zero. Energy regenerates over 24 hours, so if volume stays consistently high you will start burning TRX without a top-up.

Delegation failures. When delegateresource fails because of insufficient energy, BchainPay emits an intent.resource_delegation_failed event in the webhook stream. Route it to the same on-call queue as a failed payment — it means the next transfer on that merchant will incur TRX fees.

Energy price spike. TRON's energy burn rate is published by wallet/getchainparameters as getEnergyFee (in sun). When it rises above 500 sun, consider pre-leasing energy from JustLend to cover burst rather than burning staking reserves. The threshold matters because rental pricing is fixed and independent of the dynamic burn rate.

async function getEnergyPriceSun(): Promise<number> {
  const params = await tronWeb.trx.getChainParameters();
  const param = params.find((p: { key: string }) => p.key === 'getEnergyFee');
  return param?.value ?? 420;  // fallback to 420 sun if not found
}

Energy rental as a burst lever#

Staking is optimal for baseline load. For burst — flash sales, end-of-month settlement spikes — renting energy from protocols like JustLend is often cheaper than locking additional TRX.

JustLend's energy rental is priced hourly (roughly 0.5 sun/unit/hour in early 2026) and settled in TRX. Renting 10 million energy for 24 hours costs approximately 12 TRX (~$1.44). Permanently staking the TRX to generate the same 10M energy per day requires holding 34.5 TRX ($4.14). Rental is cheaper when the burst window is shorter than ~30 days.

We do not route BchainPay's primary production traffic through rental pools because they carry smart contract and counterparty risk. Rental is a fallback path, not a primary one. Implement it as a circuit breaker: fall through to rental only when staked energy drops below 30%.

async function ensureEnergy(required: number): Promise<void> {
  const { energy_available } = await fetchResourceState();
  if (energy_available >= required) return;
 
  const deficit = required - energy_available;
  const utilizationPct = (energy_available / energy_limit) * 100;
 
  if (utilizationPct < 30) {
    // below circuit-breaker threshold — rent the deficit
    await rentEnergyFromJustLend(deficit, durationHours=24);
    metrics.increment('tron.energy.rented', deficit);
  } else {
    // still in healthy range; queue a staking top-up for next maintenance window
    alerts.warn('tron.energy.below_target', { energy_available, required });
  }
}

Bandwidth is almost never the bottleneck#

For completeness: every account's 600 free daily bandwidth units cover roughly one to two plain TRX transfers or zero to one TRC-20 transfers per day before fees apply. For a gateway sweeping hundreds of deposits, bandwidth staking is also required — but the cost is negligible compared with energy. Staking 1 TRX for bandwidth yields ~400 bandwidth units per day. A 400-byte TRC-20 transfer consumes 400 units. So 1 TRX staked covers one TRC-20 transfer's bandwidth per day, whereas the same 1 TRX staked for energy covers ~290,000 energy units (enough for ~4.5 USDT transfers). The energy position dwarfs the bandwidth position for any non-trivial payment volume.

Key takeaways#

  • A TRON USDT transfer costs ~65,000 energy. Without staking, that burns ~27 TRX at current energy prices — not zero.
  • At ~290,000 energy per staked TRX per day, 1,200 TRX covers roughly 5,000 daily USDT transfers with a safety margin.
  • Use delegateresource to pre-assign energy to each deposit address at intent creation time; recycle delegations after settlement to conserve the energy pool.
  • Monitor energy utilization at 80% as a hard alert threshold. Subscribe to intent.resource_delegation_failed webhook events to catch staking shortfalls before they become merchant-visible fees.
  • Energy rental (JustLend, etc.) is a valid burst lever — but treat it as a circuit-breaker backup, not a primary funding source.
  • Bandwidth staking matters for sweep transactions but is an order of magnitude cheaper than energy; size the energy position first, then add a small bandwidth buffer.

Try it yourself

Spin up a sandbox merchant in under 60 seconds.

One REST endpoint, signed webhooks, five chains. No credit card required.

Related reading