Solidity on TRON: Writing Smart Contracts for TVM — TRON Wiki

Solidity on TRON: Writing Smart Contracts for TVM

11 min read · ⌘K search

Solidity is the dominant language for TRON smart contracts. Developers familiar with Ethereum ERC-20 and DeFi patterns can port much of their knowledge to TRC-20 and TVM — with attention to address formats, Energy costs, and toolchain differences.

This guide covers Solidity conventions on TRON, standard token implementation, common pitfalls, and the path from code to mainnet.

Solidity → TVM pipeline

  1. Write .sol files with pragma solidity
  2. Compile via TronBox / TronIDE → bytecode + ABI
  3. Deploy with migration or TronWeb
  4. Interact via TronWeb or HTTP trigger
  5. Verify source on TronScan

Execution environment: TVM explained.

TRC-20 template

Standard fungible token using OpenZeppelin:

Code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract ExampleToken is ERC20, Ownable {
    constructor() ERC20("Example", "EXM") Ownable(msg.sender) {
        _mint(msg.sender, 1_000_000 * 10 ** decimals());
    }

    function mint(address to, uint256 amount) external onlyOwner {
        _mint(to, amount);
    }
}

mint with onlyOwner is convenient but dangerous if owner key compromised — security guide.

Address handling

  • On-chain address type is 20-byte hex internally
  • TronWeb converts Base58 T... ↔ hex for APIs
  • msg.sender is contract caller address in TVM

Always validate inputs:

Code
require(to != address(0), "zero address");

Differences from Ethereum Solidity

TopicEthereum habitTRON adjustment
Gasgasleft()Energy metering via chain
block.timestamp~12s resolution~3s blocks
tx.originAnti-patternStill anti-pattern on TRON
Chainlink oraclesWidely usedVerify TRON oracle availability
feeLimitN/ASet in TronWeb send options

Re-test reentrancy guards, call patterns, and delegatecall on Shasta.

Energy-efficient patterns

  • Pack storage variables
  • Minimize on-chain strings (name/symbol acceptable at deploy)
  • Avoid unbounded loops over user arrays
  • Use immutable and constant where possible

Expensive contracts increase USDT transfer costs for integrators.

Testing workflow

  1. TronBox compile
  2. Deploy Shasta
  3. TronWeb script: transfer, approve, transferFrom
  4. Fuzz edge cases: zero amount, max uint, reentrancy attempt

Common vulnerabilities on TRON

Same class as EVM:

  • Reentrancy
  • Integer overflow (Solidity 0.8+ has built-in checks)
  • Access control missing on mint / withdraw
  • Honeypot blacklist (malicious tokens)

Auditors apply Ethereum methodologies to TVM bytecode.

Integration with dApps

Frontend calls via TronLink-injected TronWeb:

Code
const contract = await tronWeb.contract(abi, contractAddress);
await contract.transfer(to, amount).send({ feeLimit: 100_000_000 });

Backend: send USDT programmatically.

Verify and publish ABI

Post-deploy:

  • TronScan contract verification
  • Publish ABI in docs for integrators
  • Document admin functions and ownership

Compiler version pinning

Pin exact solc version in TronBox config. TronScan verification requires matching compiler settings including optimization runs. Mismatched settings fail verification even with correct source code.

Import paths and OpenZeppelin

Use @openzeppelin/contracts versions tested on TVM. Some Ethereum-specific patterns (e.g., certain oracle interfaces) need adaptation. Test SafeERC20 for TRC-20 interactions in your contracts — non-standard tokens exist on TRON with fee-on-transfer behavior breaking naive integrations.

FAQ

Which Solidity version should I use on TRON?

Match the version supported by your TronBox or TronIDE compiler — commonly 0.8.x. Pin versions in production and verify with same compiler on TronScan.

Can I use OpenZeppelin contracts on TRON?

Yes. Import OpenZeppelin ERC20, Ownable, etc., and compile with TronBox. Verify license and version compatibility.

Is Solidity the only option?

Solidity dominates. Some tools experiment with other languages compiling to TVM — production tokens are almost all Solidity.

How do I call another contract?

interface + Contract(addr).method() pattern identical to Ethereum.

TRC-20 same file name as ERC20.sol?

OpenZeppelin package names say ERC20 but deploy to TRON as TRC-20 standard behavior.