Best practices

Production-grade best practices for writing, deploying, and operating TRON smart contracts.

📘

Prerequisites

This page collects the practices that consistently separate production-grade TRON contracts from those that ship with avoidable bugs. Apply these alongside the patterns in Security before deploying to Mainnet.

Design for Energy from day one

  • Keep loops bounded. TVM execution time is capped at 80 ms per transaction (chain parameter #13, API key getMaxCpuTimeOfOneTx — query the live value via wallet/getchainparameters rather than hard-coding 80). Any loop with an unbounded size will hit OUT_OF_TIME in production.
  • Charge storage access carefully. SSTORE is the most expensive routine opcode — far more than MSTORE. Prefer in-memory accumulation, then write to storage once.
  • Cache repeated reads. Re-reading a storage slot in the same function costs Energy each time; loading into a local variable is free after the first load.
  • Use events instead of on-chain queryable state when all you need is an off-chain indexer. See Event log.

Access control

  • Use a maintained and well-tested library, such as Ownable or AccessControl from OpenZeppelin Contracts for TRON, rather than rolling your own admin modifier.
  • Use explicit allow-lists or role checks for sensitive functions. The legacy require(tx.origin == msg.sender) pattern that rejected contract callers is now considered an anti-pattern — it can be bypassed during contract construction (when extcodesize == 0) and breaks account-abstraction interoperability. TRON's tx.origin and msg.sender distinction matches Ethereum's, but rely on it only for tracing, not for security checks.
  • Separate roles. A single owner-can-do-everything pattern is a phishing target.

Reentrancy

  • Apply the checks-effects-interactions pattern: validate, update state, then make external calls.
  • For entry points that transfer assets or modify critical state such as balances, ownership, or allowances around an external call, use the ReentrancyGuard modifier from OpenZeppelin Contracts for TRON as defense-in-depth. A reentrancy guard does not replace the checks-effects-interactions pattern. Version 5.6.0 requires the contract source and TronBox configuration to use TRON solc 0.8.20 or a later compatible version.
  • Treat any external call in a function that also modifies balance, ownership, or allowance state as a candidate for review.

For the full reentrancy walkthrough with example exploits, see Security.

Fallback and receive functions

  • Keep fallback() and receive() cheap. A TVM value call can execute one of these functions, and expensive callback logic can exhaust the caller's Energy budget and revert the call.
  • Do not rely on callback events as a complete deposit ledger. Emitting an application event is useful for TVM calls, but on TRON Mainnet, a system TransferContract can currently send TRX directly to a contract address without executing receive() or fallback(). Off-chain accounting must also scan system transfers and transaction results.

Recursive and nested calls

  • The TVM's call depth is 64 layers. Recursive contract calls need explicit depth tracking or they hit the limit in production load.
  • Always handle the possibility that a sub-call reverts. For low-level .call() or .delegatecall(), check the returned bool flag — these never revert on failure, they return false. See VM exception handling.

Deployment and upgrade

  • Deploy to testnet(Shasta/Nile) first. Always. See the Quickstart for the full flow.
  • Verify the deployed contract on TRONSCAN immediately after deployment. See Contract verification.
  • If the contract may need to evolve, use a battle-tested proxy pattern (UUPS or transparent) from day one. Retrofitting upgradeability later is expensive and risky. See Upgrading smart contracts.

After deployment

  • Monitor Energy consumption per call. A sudden change is often the first sign of an attack or misuse.
  • Keep a runbook for common incidents: what to pause, what to upgrade, who to notify.
  • Subscribe to TRON protocol announcements — proposal changes (Energy pricing, the Dynamic Energy Model, fee_limit rules) can affect your contract's cost profile. See FeeLimit & Energy cost for cost calibration.

Related resources