Solidity on TRON
Solidity language features specific to TRON: the trx unit keyword, the trcToken type for TRC-10, msg.tokenid and msg.tokenvalue, and built-in pointers to staking and voting from contracts.
Prerequisites
TRON's Solidity compiler is a fork of the upstream Solidity compiler with a small set of TRON-specific extensions. Most upstream Solidity is supported as-is, so an Ethereum contract usually compiles unchanged. The differences fall into four categories: the trx unit keyword, the trcToken type for TRC-10, message-call extras (msg.tokenid, msg.tokenvalue), and built-in pointers for staking and voting from inside a contract.
This page is the Solidity language reference. For the full SDK that wraps Stake 2.0 in idiomatic Solidity helpers, see Stake 2.0 Solidity SDK reference.
TRX as a unit keyword
Upstream Solidity has unit suffixes for ether (wei, gwei, ether). The TRON Solidity compiler adds trx as the equivalent for the native token and sun as the smallest unit:
| Unit literal | Value |
|---|---|
1 sun | 1 sun (smallest unit) |
1 trx | 1,000,000 sun |
These are usable anywhere Solidity accepts a numeric literal:
require(msg.value >= 1 trx, "Pay at least 1 TRX");
uint256 fee = 100 sun;The standard upstream wei / gwei / ether keywords are also available but should be avoided in TRON-specific code — trx and sun make the unit unambiguous.
TRC-10 token built-ins
TRC-10 is the protocol-level token type that lives outside the TVM (see TRC-10 for the full standard). TRON Solidity exposes four built-ins that let contracts handle TRC-10 tokens.
trcToken type
trcToken typetrcToken is a separate type from uint256, used to identify a specific TRC-10 token. Values can be cast between trcToken and uint256:
trcToken id = 1000001;
uint256 idAsUint = uint256(id);
trcToken back = trcToken(idAsUint);
Valid rangeA valid TRC-10
tokenIdmust be greater than 1,000,000. The compiler does not enforce this — guard withrequire(id > 1000000)when acceptingtokenIdas a parameter.
address.transferToken(value, tokenId)
address.transferToken(value, tokenId)Send a TRC-10 token from the contract to another address, in a single Solidity call:
function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) public {
require(id > 1000000);
toAddress.transferToken(tokenValue, id);
}The semantics mirror address.transfer(uint256) for TRX: the recipient must be payable, and only 2,300 Energy is forwarded to the recipient's fallback function.
address.tokenBalance(tokenId)
address.tokenBalance(tokenId)Query the TRC-10 balance of an address from inside a contract:
function getTokenBalance(address account, trcToken id) public view returns (uint256) {
return account.tokenBalance(id);
}msg.tokenid and msg.tokenvalue
msg.tokenid and msg.tokenvalueWhen a contract function is called with attached TRC-10 tokens (using CALLTOKEN at the bytecode level, or the callTokenValue and tokenId parameters in triggerSmartContract), two extra fields are populated on the msg object:
function receiveTRC10() public payable returns (trcToken, uint256) {
trcToken id = msg.tokenid;
uint256 amount = msg.tokenvalue;
return (id, amount);
}Both default to 0 when no TRC-10 token is attached. These extras are TRON-specific — they are not present on Ethereum.
Staking, voting, and resource delegation
TRON exposes Stake 2.0 staking, voting, and reward-claiming features as Solidity built-ins on the contract itself. Resource delegation and some query helpers are called as built-in helper methods on address / address payable. The full reference, including all 26 helpers, is in Stake 2.0 Solidity SDK reference.
A small selection of the most-used helpers:
// Stake TRX to acquire Bandwidth (resourceType = 0) or Energy (resourceType = 1)
freezeBalanceV2(amount, resourceType);
// Begin unstaking — starts the 14-day waiting period
unfreezeBalanceV2(amount, resourceType);
// Withdraw TRX whose 14-day waiting period has elapsed
withdrawExpireUnfreeze();
// Vote for a Super Representative
vote(srs, voteCounts);
// Claim accumulated voting rewards
withdrawReward();Compiler version support
TRON's Solidity compiler is maintained at github.com/tronprotocol/solidity. Multiple major versions are supported in the TVM:
0.4.x— earliest TVM-supported series; works for legacy contracts, including^0.4.24and^0.4.25.0.5.x— historically the most common baseline; supports^0.5.0through^0.5.16.0.6.xand0.7.x— supported.0.8.x— current recommended baseline for new contracts. Pin a concrete patch version, for examplepragma solidity 0.8.20;(without^; check the TronBox release notes for the recommended patch version).
When porting an existing Solidity contract from Ethereum, your code should compile unchanged in the matching TRON Solidity version. If you encounter version-specific issues, see Migrating from Ethereum.
Differences from upstream Solidity
A few specific divergences from the standard Solidity compiler:
gaskeyword — accepted in source for compatibility, but the underlying TVM uses Energy.gasleft()returns the remaining Energy budget for the current call.tx.gasprice— returnsenergyPricerather than a per-tx gas price.block.difficulty— always0. TRON does not use Proof-of-Work; it uses Delegated Proof-of-Stake (DPoS).block.basefee— returnsenergyPrice. EIP-1559 is not implemented.
For the full opcode-level differences, see TVM vs EVM.
Related resources
- Stake 2.0 Solidity SDK reference — full helper reference for staking, delegation, and voting from contracts
- TVM vs EVM — opcode and precompile differences
- Opcodes — full TVM opcode reference
- Migrating from Ethereum — practical porting walkthrough
- Transferring TRC-10 in smart contracts — examples of the TRC-10 built-ins
- TIP-43 — TRC-10 in smart contracts specification
Updated 9 days ago