Opcodes

Full TVM opcode reference, including TRON-specific opcodes for TRC-10, staking, and voting.

📘

Prerequisites

The TVM opcodes are the same as the EVM opcodes, with a small set of TRON-specific additions for TRC-10 tokens, staking (Stake 2.0), voting, and contract introspection. Each section below groups related opcodes; for the high-level differences from the EVM, see TVM vs EVM.

Energy entries marked [A*] link to the formula in the Appendix: Energy cost calculations.

Arithmetic — 0x00 … 0x0B

OpcodeNameEnergyInitial StackResulting StackNotes
0x00STOP0halt execution
0x01ADD3a, ba + b(u)int256 addition modulo 2²⁵⁶
0x02MUL5a, ba × b(u)int256 multiplication modulo 2²⁵⁶
0x03SUB3a, ba − b(u)int256 subtraction modulo 2²⁵⁶
0x04DIV5a, ba // buint256 division
0x05SDIV5a, ba // bint256 division
0x06MOD5a, ba % buint256 modulus
0x07SMOD5a, ba % bint256 modulus
0x08ADDMOD8a, b, N(a + b) % N(u)int256 addition modulo N
0x09MULMOD8a, b, N(a × b) % N(u)int256 multiplication modulo N
0x0AEXPA1a, ba ** buint256 exponentiation modulo 2²⁵⁶
0x0BSIGNEXTEND5b, xSIGNEXTEND(x, b)sign-extend x from (b+1) bytes to 32 bytes

Comparison and bitwise — 0x10 … 0x1E

OpcodeNameEnergyInitial StackResulting StackNotes
0x10LT3a, ba < buint256 less-than
0x11GT3a, ba > buint256 greater-than
0x12SLT3a, ba < bint256 less-than
0x13SGT3a, ba > bint256 greater-than
0x14EQ3a, ba == b(u)int256 equality
0x15ISZERO3aa == 0(u)int256 iszero
0x16AND3a, ba & bbitwise AND
0x17OR3a, ba | bbitwise OR
0x18XOR3a, ba ^ bbitwise XOR
0x19NOT3a~abitwise NOT
0x1ABYTE3i, xi-th byte of xi-th byte from the left (i starts at 0)
0x1BSHL3shift, valval << shiftshift left
0x1CSHR3shift, valval >> shiftlogical shift right
0x1DSAR3shift, valval >> shiftarithmetic shift right
0x1ECLZ5xleadingZeros(x)Osaka. Returns the number of leading zero bits in the 256-bit unsigned integer x; returns 256 when x = 0

CLZ is controlled by the Osaka governance proposal. Upgrading a node to GreatVoyage-v4.8.2 only provides the implementation; contracts cannot rely on this opcode until the corresponding proposal has been activated on the target network.

Hashing — 0x20

OpcodeNameEnergyInitial StackResulting StackNotes
0x20SHA3A2ost, lenkeccak256(mem[ost:ost+len])Keccak-256 (despite the historical "SHA3" name)

Environment — 0x30 … 0x3F

OpcodeNameEnergyInitial StackResulting StackMem / StorageNotes
0x30ADDRESS2address(this)address of executing contract
0x31BALANCE20addraddr.balancebalance, in sun
0x32ORIGIN2tx.originaddress that originated the tx
0x33CALLER2msg.senderaddress of msg sender
0x34CALLVALUE2msg.valuemsg value, in sun
0x35CALLDATALOAD3idxmsg.data[idx:idx+32]read word from msg data at index idx
0x36CALLDATASIZE2len(msg.data)length of msg data, in bytes
0x37CALLDATACOPYA3dstOst, ost, lenmem[dstOst:dstOst+len] := msg.data[ost:ost+len]copy msg data
0x38CODESIZE2len(this.code)length of executing contract's code, in bytes
0x39CODECOPYA3dstOst, ost, lenmem[dstOst:dstOst+len] := this.code[ost:ost+len]copy executing contract's code
0x3AGASPRICE2tx.gaspricereturns energyPrice on TVM
0x3BEXTCODESIZE20addrlen(addr.code)size of code at addr, in bytes
0x3CEXTCODECOPYA4addr, dstOst, ost, lenmem[dstOst:dstOst+len] := addr.code[ost:ost+len]copy code from addr
0x3DRETURNDATASIZE2sizesize of returned data from last external call
0x3ERETURNDATACOPYA3dstOst, ost, lenmem[dstOst:dstOst+len] := returndata[ost:ost+len]copy returned data from last external call
0x3FEXTCODEHASH400addrhashaddr.exists ? keccak256(addr.code) : 0

Block and chain — 0x40 … 0x4A

OpcodeNameEnergyInitial StackResulting StackNotes
0x40BLOCKHASH20blockNumblockHash(blockNum)
0x41COINBASE2block.coinbaseaddress of proposer of current block
0x42TIMESTAMP2block.timestamptimestamp of current block
0x43NUMBER2block.numbernumber of current block
0x44DIFFICULTY20always 0 on TVM (no Proof-of-Work)
0x45GASLIMIT20always 0 on TVM
0x46CHAINID2chain_idpush current chain id onto stack
0x47SELFBALANCE5address(this).balancebalance of executing contract, in sun
0x48BASEFEE2block.basefeereturns energyPrice on TVM (no EIP-1559)
0x49BLOBHASH3indexversionedHashCancun. Always returns 0 on TVM (no blob transactions)
0x4ABLOBBASEFEE2block.blobbasefeeCancun. Always returns 0 on TVM (no blob transactions)

Stack, memory, storage, control flow — 0x50 … 0x5F

OpcodeNameEnergyInitial StackResulting StackMem / StorageNotes
0x50POP2aremove item from top of stack and discard
0x51MLOADA5ostmem[ost:ost+32]read word from memory at offset ost
0x52MSTOREA5ost, valmem[ost:ost+32] := valwrite a word to memory
0x53MSTORE8A6ost, valmem[ost] := val & 0xFFwrite a single byte to memory
0x54SLOAD50keystorage[key]read word from storage
0x55SSTOREA7key, valstorage[key] := valwrite word to storage
0x56JUMP8dst$pc := dst (must land on a JUMPDEST)
0x57JUMPI10dst, cond$pc := cond ? dst : $pc + 1
0x58PC2$pcprogram counter
0x59MSIZE2len(mem)size of memory in current execution context, in bytes
0x5AGAS2gasRemainingthe amount of available Energy
0x5BJUMPDEST1valid jump destination marker; $pc := $pc + 1
0x5CTLOAD100keytransient[key]Cancun. read word from transient storage (cleared at end of tx)
0x5DTSTORE100key, valtransient[key] := valCancun. write word to transient storage (cleared at end of tx)
0x5EMCOPYA3dstOst, ost, lenmem[dstOst:dstOst+len] := mem[ost:ost+len]Cancun. memory-to-memory copy
0x5FPUSH020Shanghai. push constant 0 onto stack

Stack manipulation — PUSH, DUP, SWAP

These families share opcode-and-Energy structure — only the size of the operand or the stack position differs.

Opcode rangeNameEnergyStack effectNotes
0x60 – 0x7FPUSH1PUSH323push an N-byte immediate value onto stackN = (opcode − 0x5F). PUSH1 pushes 1 byte; PUSH32 32.
0x80 – 0x8FDUP1DUP163clone the N-th item from the top of the stackN = (opcode − 0x7F). DUP1 clones the top of stack.
0x90 – 0x9FSWAP1SWAP163swap the top of stack with the N-th item belowN = (opcode − 0x8F). SWAP1 swaps top with the next item.

Logging — 0xA0 … 0xA4

OpcodeNameEnergyInitial StackNotes
0xA0LOG0A8ost, lenLOG0(memory[ost:ost+len])
0xA1LOG1A8ost, len, topic0LOG1(memory[ost:ost+len], topic0)
0xA2LOG2A8ost, len, topic0, topic1LOG2(memory[ost:ost+len], topic0, topic1)
0xA3LOG3A8ost, len, topic0, topic1, topic2LOG3(memory[ost:ost+len], topic0, topic1, topic2)
0xA4LOG4A8ost, len, topic0, topic1, topic2, topic3LOG4(memory[ost:ost+len], topic0, topic1, topic2, topic3)

TRON-specific — TRC-10 (0xD0 … 0xD3)

OpcodeNameEnergyInitial StackResulting StackNotes
0xD0CALLTOKENA9callEnergy, addr, val, tokenId, argOst, argLen, retOst, retLensuccesscall addr with val and TRC-10 tokenId attached
0xD1TOKENBALANCE20tokenId, addressbalancebalance of address on tokenId TRC-10 token
0xD2CALLTOKENVALUE2valueTRC-10 token value attached to current call
0xD3CALLTOKENID2tokenIdTRC-10 token ID attached to current call

TRON-specific — Introspection (0xD4)

OpcodeNameEnergyInitial StackResulting StackNotes
0xD4ISCONTRACT20addressisContracttrue if address is a contract

TRON-specific — Stake 1.0 (legacy, 0xD5 … 0xD7)

Legacy. New code should use the Stake 2.0 opcodes below.

OpcodeNameEnergyInitial StackResulting StackNotes
0xD5FREEZEA10resourceType, frozenBalance, receiverAddresssuccessfreeze frozenBalance of resourceType to receiverAddress
0xD6UNFREEZE20000resourceType, targetAddresssuccessunfreeze all resourceType on targetAddress
0xD7FREEZEEXPIRETIME50resourceType, targetAddressexpireTimeexpiration of resourceType on targetAddress

TRON-specific — Voting (0xD8 … 0xD9)

OpcodeNameEnergyInitial StackResulting StackNotes
0xD8VOTEWITNESSA11amountArrayLength, amountArrayOffset, witnessArrayLength, witnessArrayOffsetsuccessvote amounts in amountArray for SRs in witnessArray
0xD9WITHDRAWREWARD20000withdrawRewardclaim accumulated voting rewards to the contract balance

TRON-specific — Stake 2.0 (0xDA … 0xDF)

Current resource-staking and delegation opcodes (TIP-467).

OpcodeNameEnergyInitial StackResulting StackNotes
0xDAFREEZEBALANCEV210000resourceType, frozenBalancesuccessstake TRX to acquire resources
0xDBUNFREEZEBALANCEV210000resourceType, unfreezeBalancesuccessbegin unstaking — starts the unstake delay (14 days on Mainnet)
0xDCCANCELALLUNFREEZEV210000successcancel all pending unstake operations
0xDDWITHDRAWEXPIREUNFREEZE10000successwithdraw TRX whose unstake waiting period has elapsed
0xDEDELEGATERESOURCE10000resourceType, delegateBalance, receiverAddresssuccessdelegate resource to another address
0xDFUNDELEGATERESOURCE10000resourceType, unDelegateBalance, receiverAddresssuccesscancel resource delegation

Calls and contract creation — 0xF0 … 0xFF

OpcodeNameEnergyInitial StackResulting StackMem / StorageNotes
0xF0CREATEA12val, ost, lenaddrcreate contract
0xF1CALLA9callEnergy, addr, val, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen] := returndatacall addr with val and arguments
0xF2CALLCODEA13gas, addr, val, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen] := returndatalike DELEGATECALL but does not propagate original msg.sender and msg.value
0xF3RETURNA14ost, lenhalt execution and return mem[ost:ost+len]
0xF4DELEGATECALLA15callEnergy, addr, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen] := returndatadelegate call — executes in caller's context (storage, balance, msg.sender)
0xF5CREATE2A16val, ost, len, saltaddraddr = keccak256(0x41 ++ address(this) ++ salt ++ keccak256(mem[ost:ost+len]))[12:]
0xFASTATICCALLA15gas, addr, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen] := returndatacall without permitting state changes
0xFDREVERTA14ost, lenrevert(mem[ost:ost+len]) — rolls back state, refunds remaining Energy
0xFFSUICIDEA17addrhalt execution; behavior depends on ALLOW_TVM_SELFDESTRUCT_RESTRICTION (active on Mainnet) — for contracts not created in the current transaction, only transfers balance and assets instead of deleting the account. Also exposed as SELFDESTRUCT in Solidity. See TVM vs EVM — SELFDESTRUCT.

Osaka precompiled contract

GreatVoyage-v4.8.2 implements P256VERIFY (TIP-7951) for secp256r1/P-256 signature verification. The precompiled contract is located at 0x0000000000000000000000000000000000000100 and has a fixed cost of 6900 Energy.

The input must be exactly 160 bytes, formed by concatenating five 32-byte fields: hash || r || s || qx || qy. A valid signature returns a 32-byte value of 1. An invalid input length, signature, or public key returns empty bytes without reverting the call.

Like CLZ, P256VERIFY is controlled by the Osaka governance proposal. Before deploying contracts that depend on it, confirm that the proposal has been activated on the target network instead of relying on the node version alone.

Appendix: Energy cost calculations

A01: memNeed(offset, size)

Calculate the memory needed.

  • offset — the start position in memory.
  • size — data length to handle, beginning at offset.
  • Returns offset + size.

A02: calcMemEnergy(oldMemorySize, memorySize, copySize)

Calculate the memory Energy cost.

  • oldMemorySize — old memory size.
  • memorySize — new memory size after the operation.
  • copySize — for copy operations, the data size to copy.
  • memWords = (memorySize + 31) / 32
  • oldMemWords = oldMemorySize / 32
  • energyCost = 3 * memWords + memWords² / 512 − (3 * oldMemWords + oldMemWords² / 512) + 3 * ((copySize + 31) / 32)

A03: penalty(energyCost)

If the Dynamic Energy Model is allowed, return the penalty.

  • DYNAMIC_ENERGY_FACTOR = 10000
  • Factor — contract context factor.
  • penalty = energyCost * factor / DYNAMIC_ENERGY_FACTOR − energyCost
  • return penalty > 0 ? penalty : 0

A04: isDeadAccount(address)

Returns true if the address is not a contract, otherwise false.

A05: sizeInWords(len)

Returns len == 0 ? 0 : (len − 1) / 32 + 1.


A1: EXP Energy cost

  • byte_len_exponent — number of bytes in the exponent (b in the stack representation).
  • energy_cost = 10 + 10 * byte_len_exponent

A2: SHA3 Energy cost

  • energy_cost = 30 + calcMemEnergy(oldMemSize, memNeed(ost, len), 0)

A3: COPY operations

Applies to CALLDATACOPY, CODECOPY, RETURNDATACOPY, and MCOPY (not EXTCODECOPY).

  • energy_cost = calcMemEnergy(oldMemSize, memNeed(dstOst, len), len)

A4: EXTCODECOPY

  • energy_cost = 20 + calcMemEnergy(oldMemSize, memNeed(dstOst, len), len)

A5: MLOAD, MSTORE

  • energy_cost = calcMemEnergy(oldMemSize, memNeed(ost, 32), 0)

A6: MSTORE8

  • energy_cost = calcMemEnergy(oldMemSize, memNeed(ost, 1), 0)

A7: SSTORE

  • oldValue — old value of storage[key].
  • energy_cost = (oldValue == null && val != 0) ? 20000 : 5000

A8: LOG0 to LOG4

  • nTopics — number of topics.
  • energyCost = 375 + 375 * nTopics + 8 * len + calcMemEnergy(oldMemSize, memNeed(ost, len), 0)

A9: CALLTOKEN, CALL

energyCost_1 = 40
             + (val != 0 ? 9000 : 0)
             + (val != 0 && isDeadAccount(addr) ? 25000 : 0)
             + calcMemEnergy(oldMemSize,
                             max(memNeed(orgOst, orgLen), memNeed(retOst, retLen)),
                             0)
energyCost_2     = energyCost_1 + penalty(energyCost_1)
energyLimitLeft  = energyLimit - energyCost_2
energyCost       = energyCost_2 + min(callEnergy, energyLimitLeft)

A10: FREEZE

  • energyCost = 20000 + (isDeadAccount(receiverAddress) ? 25000 : 0)

A11: VOTEWITNESS

energyCost = 30000 + (ALLOW_ENERGY_ADJUSTMENT
    ? calcMemEnergy(oldMemSize,
                    max(memNeed(amountArrayOffset, amountArrayLength),
                        memNeed(witnessArrayOffset, witnessArrayLength)),
                    0)
    : calcMemEnergy(oldMemSize,
                    max(memNeed(amountArrayOffset, amountArrayLength * 32 + 32),
                        memNeed(witnessArrayOffset, witnessArrayLength * 32 + 32)),
                    0))

A12: CREATE

  • energyCost = 32000 + calcMemEnergy(oldMemSize, memNeed(ost, len), 0)

A13: CALLCODE

energyCost_1 = 40
             + (val != 0 ? 9000 : 0)
             + calcMemEnergy(oldMemSize,
                             max(memNeed(orgOst, orgLen), memNeed(retOst, retLen)),
                             0)
energyCost_2     = energyCost_1 + penalty(energyCost_1)
energyLimitLeft  = energyLimit - energyCost_2
energyCost       = energyCost_2 + min(callEnergy, energyLimitLeft)

A14: RETURN, REVERT

  • energy_cost = calcMemEnergy(oldMemSize, memNeed(ost, len), 0)

A15: DELEGATECALL, STATICCALL

energyCost_1     = 40 + calcMemEnergy(oldMemSize,
                                      max(memNeed(orgOst, orgLen), memNeed(retOst, retLen)),
                                      0)
energyCost_2     = energyCost_1 + penalty(energyCost_1)
energyLimitLeft  = energyLimit - energyCost_2
energyCost       = energyCost_2 + min(callEnergy, energyLimitLeft)

A16: CREATE2

  • energyCost = 32000 + calcMemEnergy(oldMemSize, memNeed(ost, len), 0) + 6 * sizeInWords(len)

A17: SUICIDE

Cost depends on which proposal gates are active:

GateLive obtainer accountDead obtainer account
Base (no gates)00
ALLOW_ENERGY_ADJUSTMENT only025,000 (NEW_ACCT_CALL)
ALLOW_TVM_SELFDESTRUCT_RESTRICTION (active on Mainnet)5,00030,000 (5,000 + 25,000)

See TVM vs EVM — SELFDESTRUCT restricted behavior for the semantic shift that accompanies the cost change.


Related resources