Smart contracts introduction

What smart contracts are, how they work on TRON, and what makes the TRON contract model different from a vanilla EVM contract.

📘

Prerequisites

What is a smart contract

A smart contract is an application program that runs on the TRON blockchain. Once deployed, its code is immutable (unless designed with an upgrade pattern) and every node in the network executes it identically, producing verifiable state transitions. A smart contract is a type of TRON account — it has its own address and balance, and can execute internal transfers or contract-to-contract calls when invoked by an externally owned account, but is not controlled by any user and runs only as programmed. User accounts interact with it by submitting transactions that execute one of its functions; those interactions are irreversible once confirmed.

On TRON, smart contracts run inside the TRON Virtual Machine (TVM) — a deterministic, stack-based execution environment compatible with most Ethereum EVM opcodes, with TRON-specific opcodes for TRC-10, staking, voting, and related features. Most Solidity contracts written for Ethereum can be deployed on TRON with minimal changes (a few TRON-specific differences like Energy vs gas and address format need to be accounted for). See Migrating from Ethereum for the full porting guide.

A useful metaphor is a vending machine: with the right inputs, a certain output is guaranteed. For a vending machine, the logic is money + snack selection = snack dispensed. A smart contract works the same way — the logic is programmed, the inputs are transactions, and the outputs are verifiable state changes.

Example: a simple vending machine contract

pragma solidity 0.8.7;

contract VendingMachine {

    // Declare state variables of the contract
    address public owner;
    mapping (address => uint) public cupcakeBalances;

    // When 'VendingMachine' contract is deployed:
    // 1. set the deploying address as the owner of the contract
    // 2. set the deployed smart contract's cupcake balance to 100
    constructor() {
        owner = msg.sender;
        cupcakeBalances[address(this)] = 100;
    }

    // Allow the owner to increase the smart contract's cupcake balance
    function refill(uint amount) public {
        require(msg.sender == owner, "Only the owner can refill.");
        cupcakeBalances[address(this)] += amount;
    }

    // Allow anyone to purchase cupcakes
    function purchase(uint amount) public payable {
        require(msg.value >= amount * 1 trx, "You must pay at least 1 TRX per cupcake");
        require(cupcakeBalances[address(this)] >= amount, "Not enough cupcakes in stock to complete this purchase");
        cupcakeBalances[address(this)] -= amount;
        cupcakeBalances[msg.sender] += amount;
    }
}

Like a vending machine removes the need for a vendor employee, smart contracts can replace intermediaries in many industries.

Properties of smart contracts

Permissionless

Anyone can write a smart contract and deploy it to the TRON network. You need to know how to code in a smart contract language, and have enough TRX to deploy your contract. Deploying a smart contract is a transaction (CreateSmartContract type) — you pay Bandwidth for the transaction size and Energy for storing the bytecode and running the constructor. See FeeLimit & Energy cost for sizing.

TRON has a developer-friendly language for writing smart contracts: Solidity. A contract must be compiled to TVM bytecode before deployment. The bytecode is then stored on-chain at the contract's address, and the TVM executes it whenever the contract is called.

Composability

Smart contracts are public on the TRON network and can be thought of as open APIs. You can call other smart contracts in your own smart contract to greatly extend what's possible. Contracts can even deploy other contracts. You do not need to write your own smart contract from scratch to become a DApp developer — you can compose existing contracts. For example, you can use the existing SunSwap contracts to handle token swap logic in your app.

Limitations of smart contracts

Smart contracts cannot talk to the outside world directly

Smart contracts cannot communicate directly with external systems, so they cannot get information about real-world events on their own. This bottleneck limits smart contract application scenarios, but it is by design — relying on arbitrary external information would jeopardize consensus, which is important for security and decentralization. Oracles solve this problem by feeding signed external data on-chain.

Maximum execution time

To ensure the high throughput and stable operation of the network, TRON caps the CPU time per transaction at 80 ms (current Mainnet value). This is needed because TRON produces a new block every 3 seconds. The cap is chain parameter #13 (API key getMaxCpuTimeOfOneTx) and the Super Representative (SR) committee can modify it through proposals. Query the current value via wallet/getchainparameters and look up the getMaxCpuTimeOfOneTx key — do not assume 80 is fixed.

Complex contracts can exceed the per-transaction CPU deadline and fail with OUT_OF_TIME. After a timeout, the TVM accounts for Energy up to the limit calculated before execution.

Reduce timeout risk by limiting the work performed in each transaction: bound loops and batches, split expensive operations into resumable transactions, and keep deployment constructors lightweight by moving substantial initialization into later transactions. Calling smaller helper contracts within the same transaction does not reset the CPU deadline. See Smart contract errors and VM exception handling.

TRON-specific context

Where TRON smart contracts differ from Ethereum:

  • Resource model — TRON meters execution through Energy (CPU/storage work) rather than a single gas unit. You obtain Energy by either staking TRX for an Energy quota that recovers linearly over a rolling 24-hour window or by burning TRX directly at execution time. See Resource model for details.
  • Deployment fee — Deploying a contract requires Energy and Bandwidth — covered by either pre-staked TRX or by burning TRX at execution time. Bytecode storage and the constructor call together drive the bulk of the cost. See FeeLimit & Energy cost.
  • Address format — In wallet, RPC, and Base58Check external representation, TRON addresses are 21 bytes: a 0x41 prefix followed by the same 20-byte Keccak-256 hash that Ethereum derives. On the wire, TRON encodes them as Base58Check (T...) instead of Ethereum's hex (0x...). Inside the TVM, TRON uses the 20-byte address data with the prefix removed. See Accounts and keys.

Next steps


Related resources