The most demoralizing message in crypto is not a hack or a rug pull. It's this one: “insufficient funds for gas.” You hold $250 of USDT. It is yours, it is on-chain, and you cannot move it — because the chain wants its fee in a different token, one you've never bought and shouldn't have to think about.
Our users hold stablecoins. Almost none of them hold ETH, BNB, POL, or TRX, and we think that's correct — a person spending USDTs on our platform should never need a side-quest into gas token portfolio management. So we made it a hard product constraint:
A transaction must work from a wallet that has never held a gas token — and never will.
That one constraint forces two completely different machines, because the two chain families where our users actually live — EVM networks and TRON — price their blockspace in incompatible ways. On EVM chains we made the account itself programmable, so someone else can pay its gas. On TRON, where no such protocol exists, we rent the fee resource on an open market, an hour at a time. This post is about both machines, and the reliability scaffolding underneath them.
EVM: the account is the trick
On EVM chains, the escape hatch is account abstraction (ERC-4337). Instead of giving each user a plain key-pair address, we give them a smart contract account — a small contract that owns funds and executes calls, with its own validation logic. The difference that matters here: a plain address must pay for its own transactions, but a smart account's operations travel through a separate mempool as UserOperation objects, where a paymaster — a contract with a prepaid gas deposit — can volunteer to cover the cost, subject to a sponsorship policy we control.
A transaction, end to end, looks like this:
- The API validates the request, quotes the fee, locks the user's ledger balance, and enqueues the send. Nothing irreversible happens on the request path.
- A queue consumer builds the user operation: the calldata is just
transfer(to, amount)on the token contract, executed from the user's smart account. - The paymaster co-signs, committing its deposit to pay for this specific operation under our sponsorship policy.
- A bundler wraps the signed operation into a real transaction to the chain's
EntryPointcontract, which verifies everything and executes the transfer — debiting gas from the paymaster's deposit, not from the user's account.
The user's address holds tokens and nothing else. Not at signup, not at deposit, not when sending. There is no top-up job shuttling dust to thousands of addresses, no stranded gas to sweep back, no “minimum ETH balance” support article.
Counterfactual accounts: the address exists before the contract
The subtle part of this design is what happens at signup: nothing. No deployment transaction, no on-chain footprint, no cost. A smart account's address is computed with CREATE2— a pure function of the factory, the account code, and a salt we derive from the user's identity. We can hand out the address immediately and deposits to it just work, because on EVM chains value can be sent to any address, contract or not. The account is counterfactual: everyone can agree on where it will live without it existing yet.
The contract materializes lazily. The first outbound transfer's user operation carries an initCode field; the EntryPoint deploys the account and executes the transfer in the same transaction — and the deployment gas rides on the same sponsorship as everything else. Users who never send never cost a deployment.
Because the inputs are deterministic and identical everywhere, the same user gets the same address on every EVM chain we support. One derivation, one column in the database, and a deposit flow that doesn't care whether the funds arrived on Ethereum, Base, Polygon, or BNB Chain. When we added our latest EVM network, no wallets needed to be created — every user already had an address there.
Honesty about the trade-off: an ERC-4337 transfer is heavier than a raw one. We budget roughly 120k gas for a sponsored token transfer where a plain transfer costs about 65k— validation and indirection aren't free. We consider that premium the price of deleting an entire class of operational work, and it's priced into the transaction fee like any other cost.
TRON: no protocol will save you
TRON has no account abstraction, no paymasters, no user operation mempool. What it has instead is a resource model that is genuinely different, and any honest gasless design has to work with its grain.
Fees on TRON are paid in two metered resources. Bandwidth covers transaction bytes — cheap, and all a native TRX transfer needs. Energy covers contract execution, and TRC-20 transfers are contract execution. A USDT transfer consumes roughly 65,000energy — and here's the cliff that surprises everyone: if the recipient's USDT balance is zero, the same transfer costs about double, around 130,000 energy, because writing a balance into a fresh storage slot is priced as new state.
An account acquires energy in one of two ways: stake TRX and receive a continuous energy allowance, or hold no stake and let the protocol burn your TRX at a fixed network rate — currently 210 sunper energy unit (a sun is a millionth of a TRX). Run the numbers on burning and they're grim: 65,000 × 210 ≈ 13.7 TRX per transfer, and ~27 TRX when the recipient starts from zero. Several dollars of gas, per transfer, burned.
There's one more trap. A TRON address that has never received TRX does not exist on-chain. It can't broadcast anything — and receiving USDT alone does not activate it. So every sending wallet needs a small activation transfer (about 1 TRX) before it can do anything at all. TRON's gas problem isn't one problem; it's three stacked on each other.
The energy market
The way out comes from TRON's own staking mechanics: staked TRX generates energy continuously, and the protocol allows that energy to be delegated to another account. Around this grew a real two-sided market — large holders stake TRX at scale and sell short-lived delegations to anyone who needs to move a token. The market price floats around 25–75 sunper energy unit for a one-hour lease, against the protocol's fixed burn rate of 210. Same resource, two prices — one set by governance, one set by supply and demand.
So a TRON transfer runs like this:
- Probe the recipient first. A free read-only
balanceOfcall decides whether we're on the cheap side of the cliff or the expensive one: we rent66,000energy if the recipient already holds USDT,132,000if they don't. If the probe itself fails, we rent the larger amount — the failure mode of guessing low is a dead transfer, so we never guess low. - Quote, with guards.We ask the market for a price and refuse to order if it exceeds our cap (well below the burn rate — paying near-burn prices on a rental market means something is wrong), or if the market can't fill the full amount immediately. Partial fills and deferred fills are explicitly rejected: the transfer broadcasts seconds after the delegation lands, so energy that arrives late is energy we paid for and can't use.
- Rent, then verify.The delegation is an on-chain fact, so we poll the sending account's energy budget until it reflects the lease — up to 60 seconds — rather than trusting the marketplace's acknowledgment.
- Broadcast with a tripwire. The transfer is built with a fee limit of
1 sun— deliberately absurd. If the energy is actually there, the transfer consumes it and the limit is irrelevant. If something upstream failed, the transaction fails loudly instead of silently falling back to burning tens of TRX. We'd rather retry a failed send than discover a month later that a bug quietly multiplied our gas bill by six.
What does the sending wallet itself need? Just 2 TRX — enough to cover its one-time activation and the bandwidth bytes of the transfer. Under the burn model that float was 30 TRX per wallet, parked across every wallet in the fleet. The rental model cut the per-transfer cost by roughly 70–85% and shrank the per-wallet float by 15×:
| Burning TRX | Renting energy | |
|---|---|---|
| Price per energy unit | 210 sun (fixed by protocol) | ~25–75 sun (market, hard-capped) |
| Cost per USDT transfer | ~14–27 TRX | ~2–5 TRX |
| TRX float per wallet | ~30 TRX | 2 TRX |
| Where the money goes | Burned | To stakers, via the market |
(Prices as of writing; the market moves. The burn rate only moves by governance vote — historically upward.)
The mode is a switch, not an architecture: rent, burn, or auto, where autofalls back to burning if the rental market is down or drained. The burn path is worse economics but identical correctness, which makes it a fine disaster mode — and because we check the account's live energy budget before ordering, a retry that finds an earlier delegation still active skips the rental entirely and sends for free.
The scaffolding that keeps money safe
Sponsoring gas means our infrastructure, not the user's key, is the thing broadcasting transactions — which raises the stakes on double-broadcasting. Three rules hold the line, on both chain families:
- Claim before broadcast.Transactions move through a queue with at-least-once delivery, so the consumer's first act is a conditional database update —
queued → submitting. Zero rows updated means another delivery already owns this transaction, and the duplicate exits. The broadcast itself is never raced. - Never retry past a broadcast attempt.If a broadcast errors, we cannot know whether the transaction actually reached the network — a timeout is not a failure. Retrying “to be safe” risks sending the money twice, so an ambiguous broadcast is parked for reconciliation instead of retried. Only errors that occur strictly before any broadcast attempt re-queue.
- Two-phase ledger movement.The user's balance is locked when the request is accepted and only finalized after a confirmed broadcast. And every gas-side action — an activation, a TRX top-up, an energy rental — is recorded in its own audit table, so the question “where did our gas budget go this month” is a query, not an investigation.
The user-facing economics stay simple: the fee is quoted in the asset being sent and deducted from the amount, priced from a live estimate of the real chain cost — with static fallbacks so a flaky RPC can never block a send. The recipient gets the net; no one ever touches gas.
Two philosophies, one invariant
It's worth noticing that these aren't two implementations of one idea — they're two different ideas. EVM solved gas abstraction in protocol: standardize programmable accounts, and let anyone volunteer to pay. TRON solved it with a market: make the fee resource stakeable and delegable, and let price discovery do the rest. One is an engineering answer, the other an economic one — and a wallet infrastructure that spans both has to be fluent in both.
The user's experience is the invariant: stablecoins in, stablecoins out, and gas as our implementation detail — never their problem.
Every design above serves that one sentence. The chains disagree about almost everything; our users never have to know.