Home指南API 参考手册
指南API 参考手册社区Discord博客FAQ漏洞赏金公告中心English(英文版)Log In
指南

操作码

TVM 操作码

TRON 虚拟机(TVM)的操作码与以太坊虚拟机(EVM)兼容,并额外包含了一些 TRON 网络的特有操作码。请参阅下表获取各操作码的详细信息。

操作码名称能量初始栈 (Initial Stack)结果栈 (Resulting Stack)内存 / 存储注释
0x00STOP0停止执行
0x01ADD3a, ba + b(u)int256 的模 2**256 加法
0x02MUL5a, ba * b(u)int256 的模 2**256 乘法
0x03SUB3a, ba - b(u)int256 的模 2**256 减法
0x04DIV5a, ba // buint256 除法
0x05SDIV5a, ba // bint256 除法
0x06MOD5a, ba % buint256 取模
0x07SMOD5a, ba % bint256 取模
0x08ADDMOD8a, b, N(a + b) % N(u)int256 模 N 加法
0x09MULMOD8a, b, N(a * b) % N(u)int256 模 N
0x0AEXPA1a, ba ** buint256 exponentiation modulo 2**256
0x0BSIGNEXTEND5b, xSIGNEXTEND(x, b)sign extendx(b+1) 字节符号扩展至 32 字节
0x0C-0x0Finvalid
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, bab
0x18XOR3a, ba ^ bbitwise XOR
0x19NOT3a~abitwise NOT
0x1ABYTE3i, x(x >> (248 - i * 8)) && 0xFFith byte of (u)int256 x, from the left (i start from 0)
0x1BSHL3shift, valval << shift
0x1CSHR3shift, valval >> shift逻辑移动
0x1DSAR3shift, valval >> shift左移arithmetic shift right
0x20SHA3A2ost, lenkeccak256(mem[ost:ost+len-1])keccak256
0x21-0x2Finvalid
0x30ADDRESS2.address(this)address of executing contract
0x31BALANCE20addraddr.balancebalance, in sun
0x32ORIGIN2.tx.originaddress that originated the tx
0x33CALLER2.msg.senderaddress of msg sender
0x34CALLVALUE2.msg.valuemsg value, in sun
0x35CALLDATALOAD3idxmsg.data[idx:idx+32]read word from msg data at indexidx
0x36CALLDATASIZE2.len(msg.data)length of msg data, in bytes
0x37CALLDATACOPYA3dstOst, ost, len.mem[dstOst:dstOst+len-1] := msg.data[ost:ost+len-1]copy msg data
0x38CODESIZE2.len(this.code)length of executing contract's code, in bytes
0x39CODECOPYA3dstOst, ost, len.mem[dstOst:dstOst+len-1] := this.code[ost:ost+len-1]
0x3AGASPRICE2.tx.gaspricegas price of tx
0x3BEXTCODESIZE20addrlen(addr.code)size of code at addr, in bytes
0x3CEXTCODECOPYA4addr, dstOst, ost, len.mem[dstOst:dstOst+len-1] := addr.code[ost:ost+len-1]copy code from addr
0x3DRETURNDATASIZE2.sizesize of returned data from last external call, in bytes
0x3ERETURNDATACOPYA3dstOst, ost, len.mem[dstOst:dstOst+len-1] := returndata[ost:ost+len-1]copy returned data from last external call
0x3FEXTCODEHASH400addrhashhash = addr.exists ? keccak256(addr.code) : 0
0x40BLOCKHASH20blockNumblockHash(blockNum)
0x41COINBASE2.block.coinbaseaddress of proposer of current block
0x42TIMESTAMP2.block.timestamptimestamp of current block
0x43NUMBER2.block.numbernumber of current block
0x44DIFFICULTY2.0block’s difficulty,
0x45GASLIMIT2.block.gaslimitgas limit of current block
0x46CHAINID2.chain_idpush current chain id onto stack
0x47SELFBALANCE5.address(this).balancebalance of executing contract, in sun
0x48BASEFEE2.block.basefeebase fee of current block
0x50POP2..remove item from top of stack and discard it
0x51MLOADA5ostmem[ost:ost+32]read word from memory at offsetost
0x52MSTOREA5ost, val.mem[ost:ost+32] := valwrite a word to memory
0x53MSTORE8A6ost, val.mem[ost] := val && 0xFFwrite a single byte to memory
0x54SLOAD50keystorage[key]read word from storage
0x55SSTOREA7key, val.storage[key] := valwrite word to storage
0x56JUMP8dst.$pc := dstmark thatpcis only assigned ifdstis a valid jumpdest
0x57JUMPI10dst, condition.$pc := condition ? dst : $pc + 1
0x58PC2.$pcprogram counter
0x59MSIZE2.len(mem)size of memory in current execution context, in bytes
0x5AGAS2.gasRemainingthe amount of available gas
0x5BJUMPDEST1$pc := $pc + 1
0x5FPUSH02.uint8push the constant value 0 onto stack
0x60PUSH13.uint8push 1-byte value onto stack
0x61PUSH23.uint16push 2-byte value onto stack
0x62PUSH33.uint24push 3-byte value onto stack
0x63PUSH43.uint32push 4-byte value onto stack
0x64PUSH53.uint40push 5-byte value onto stack
0x65PUSH63.uint48push 6-byte value onto stack
0x66PUSH73.uint56push 7-byte value onto stack
0x67PUSH83.uint64push 8-byte value onto stack
0x68PUSH93.uint72push 9-byte value onto stack
0x69PUSH103.uint80push 10-byte value onto stack
0x6APUSH113.uint88push 11-byte value onto stack
0x6BPUSH123.uint96push 12-byte value onto stack
0x6CPUSH133.uint104push 13-byte value onto stack
0x6DPUSH143.uint112push 14-byte value onto stack
0x6EPUSH153.uint120push 15-byte value onto stack
0x6FPUSH163.uint128push 16-byte value onto stack
0x70PUSH173.uint136push 17-byte value onto stack
0x71PUSH183.uint144push 18-byte value onto stack
0x72PUSH193.uint152push 19-byte value onto stack
0x73PUSH203.uint160push 20-byte value onto stack
0x74PUSH213.uint168push 21-byte value onto stack
0x75PUSH223.uint176push 22-byte value onto stack
0x76PUSH233.uint184push 23-byte value onto stack
0x77PUSH243.uint192push 24-byte value onto stack
0x78PUSH253.uint200push 25-byte value onto stack
0x79PUSH263.uint208push 26-byte value onto stack
0x7APUSH273.uint216push 27-byte value onto stack
0x7BPUSH283.uint224push 28-byte value onto stack
0x7CPUSH293.uint232push 29-byte value onto stack
0x7DPUSH303.uint240push 30-byte value onto stack
0x7EPUSH313.uint248push 31-byte value onto stack
0x7FPUSH323.uint256push 32-byte value onto stack
0x80DUP13aa, aclone 1st value on stack
0x81DUP23_, aa, _, aclone 2nd value on stack
0x82DUP33_, _, aa, _, _, aclone 3rd value on stack
0x83DUP43_, _, _, aa, _, _, _, aclone 4th value on stack
0x84DUP53..., aa, ..., aclone 5th value on stack
0x85DUP63..., aa, ..., aclone 6th value on stack
0x86DUP73..., aa, ..., aclone 7th value on stack
0x87DUP83..., aa, ..., aclone 8th value on stack
0x88DUP93..., aa, ..., aclone 9th value on stack
0x89DUP103..., aa, ..., aclone 10th value on stack
0x8ADUP113..., aa, ..., aclone 11th value on stack
0x8BDUP123..., aa, ..., aclone 12th value on stack
0x8CDUP133..., aa, ..., aclone 13th value on stack
0x8DDUP143..., aa, ..., aclone 14th value on stack
0x8EDUP153..., aa, ..., aclone 15th value on stack
0x8FDUP163..., aa, ..., aclone 16th value on stack
0x90SWAP13a, bb, aswap the 1st item from the stack with the top
0x91SWAP23a, _, bb, _, aswap the 2nd item from the stack with the top
0x92SWAP33a, _, _, bb, _, _, aswap the 3rd item from the stack with the top
0x93SWAP43a, _, _, _, bb, _, _, _, aswap the 4th item from the stack with the top
0x94SWAP53a, ..., bb, ..., aswap the 5th item from the stack with the top
0x95SWAP63a, ..., bb, ..., aswap the 6th item from the stack with the top
0x96SWAP73a, ..., bb, ..., aswap the 7th item from the stack with the top
0x97SWAP83a, ..., bb, ..., aswap the 8th item from the stack with the top
0x98SWAP93a, ..., bb, ..., aswap the 9th item from the stack with the top
0x99SWAP103a, ..., bb, ..., aswap the 10th item from the stack with the top
0x9ASWAP113a, ..., bb, ..., aswap the 11th item from the stack with the top
0x9BSWAP123a, ..., bb, ..., aswap the 12th item from the stack with the top
0x9CSWAP133a, ..., bb, ..., aswap the 13th item from the stack with the top
0x9DSWAP143a, ..., bb, ..., aswap the 14th item from the stack with the top
0x9ESWAP153a, ..., bb, ..., aswap the 15th item from the stack with the top
0x9FSWAP163a, ..., bb, ..., aswap the 16th item from the stack with the top
0xA0LOG0A8ost, len.LOG0(memory[ost:ost+len-1])
0xA1LOG1A8ost, len, topic0.LOG1(memory[ost:ost+len-1], topic0)
0xA2LOG2A8ost, len, topic0, topic1.LOG2(memory[ost:ost+len-1], topic0, topic1)
0xA3LOG3A8ost, len, topic0, topic1, topic2.LOG3(memory[ost:ost+len-1], topic0, topic1, topic2)
0xA4LOG4A8ost, len, topic0, topic1, topic2, topic3.LOG4(memory[ost:ost+len-1], topic0, topic1, topic2, topic3)
0xD0CALLTOKENA9callEnergy, addr, val, tokenId, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] := returndatacall the addr with val and argument.
0xD1TOKENBALANCE20tokenId, addressbalancebalance of address on tokenId trc10 token
0xD2CALLTOKENVALUE2.valuecall token value
0xD3CALLTOKENID2tokenIdtoken id
0xD4ISCONTRACT20addressisContract判断一个地址是否为合约
0xD5FREEZEA10resouceType, frozenBalance, receiverAddresssuccessFreeze frozenBalance resource of resourceType to receiverAddress
0xD6UNFREEZE20000resourceType, targetAddresssuccessUnfreeze all resource of resourceType on targetAddress
0xD7FREEZEEXPIRETIME50resourceType, targetAddressexpireTimeexpireTime of resourceType on targetAddress
0xD8VOTEWITNESSA11amountArrayLength, amountArrayOffset, witnessArrayLength, witnessArrayOffsetsuccessvote amount in amountArray for corresponding witness in witnessArray.
0xD9WITHDRAWREWARD20000.withdrawRewardwithdrawReward
0xDAFREEZEBALANCEV210000resourceType, frozenBalancesuccessfreeze balance v2
0xDBUNFREEZEBALANCEV210000resouceType, unfreezeBalancesuccessunfreeze balance v2
0xDCCANCELALLUNFREEZEV210000.successcancel all unfreeze V2 balance
0xDDWITHDRAWEXPIREUNFREEZE10000.successWithdraw expired unfreeze balance
0xDEDELEGATERESOURCE10000resouceType, delegateBalance, receiverAddresssuccessDelegate resource
0xDFUNDELEGATERESOURCE10000resourceType, unDelegateBalance, receiverAddresssuccessUndelegate resource
0xF0CREATEA12val, ost, len.create contract
0xF1CALLA9callEnergy, addr, val, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] := returndatacall codeAddress with value and argument.
0xF2CALLCODEA13gas, addr, val, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] = returndatasame as DELEGATECALL, but does not propagate original msg.sender and msg.value
0xF3RETURNA14ost, len.halt execution and return mem[ost:ost+len-1]
0xF4DELEGATECALLA15callEnergy, addr, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] := returndatadelegate call
0xF5CREATE2A16val, ost, len, saltaddraddr = keccak256(0x41 ++ address(this) ++ salt ++ keccak256(mem[ost:ost+len-1]))[12:]
0xFASTATICCALLA15gas, addr, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] := returndata
0xFDREVERTA14ost, len.revert(mem[ost:ost+len-1])
0xFFSUICIDEA17addr.halt execution and register account for later deletion

附录:能量消耗计算

A01: memNeed(offset, size)

计算操作所需的内存大小。

  • offset:内存中的起始位置。
  • size: 从 offset 开始需要处理的数据长度。
  • Return : offset + size

A02: calcMemEnergy(oldMemorySIze, memorySize, copySize)

计算内存操作消耗的能量。

  • oldMemorySize:操作前的内存大小。
  • memorySize: 操作后的新内存大小。
  • copySize : 如果操作涉及数据拷贝,copySize为拷贝的数据大小。
  • memWords = (memorySize + 31) / 32
  • oldMemWords = oldMemorySize / 32
  • energyCost = 3 * memWords + memWords^2 / 512 - (3 * oldMemWords + oldMemWords^2 / 512) + 3 *((copySize + 31) / 32)

A03: penalty(energyCost)

如果允许动态能量,则返回惩罚值 (penalty)。

  • DYNAMIC_ENERGY_FACTOR = 10000
  • Factor:合约上下文因子。
  • Penalty = energyCost * factor / DYNAMIC_ENERGY_FACTOR - energyCost
  • 返回:penalty > 0 ? penalty : 0

A04: isDeadAccount(address)

判断一个地址是否为非合约的空账户。如果地址不是一个合约账户,返回 true,否则返回 false。

A05: sizeInWords(len)

计算长度 len 占用的字数(一个字为32字节)。

返回 len == 0 ? 0 : (len - 1) / 32 + 1


A1: EXP 能量消耗

  • byte_len_exponent: 指数 b 的字节长度。the number of bytes in the exponent (exponent is b in the stack representation)

计算:

  • energy_cost = 10 + 10 * byte_len_exponent

A2: SHA3-energyCost

  • energy_cost = 30 + [calcMemEnergy](#a02-calcmemenergyoldmemorysize-memorysize-copysize)(oldMemSize, [memNeed](#a01-memneedoffset-size)(ost, len), 0)

A3: *COPY 系列操作

The following applies for the operations CALLDATACOPY, CODECOPY, and RETURNDATACOPY (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 : (oldValue != null && value == 0) ? 5000 : 5000

A8: LOG0, LOG1 … LOG4

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

A9: CALLTOKEN, CALL

  • energyCost_1 = 40 + (val != 0 ? 9000 : 0) +

(value != 0 && isDeadAccount(addr) ? 25000 : 0) +

calcMemEnergy(oldMemSize, max(memNeed(orgOst, orgLen), memNeed(retOst, retLen)), 0)

  • energyCost_2 = energeCost_1 + penalty(energyCost_1)
  • energyLimitLeft = energeLimit - 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 = energeCost_1 + penalty(energyCost_1)
  • energyLimitLeft = energeLimit - energyCost_2
  • energyCost = energyCost_2 + min(callEnergy, energyLimitLeft)

A14: RETURN, REVERT

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

A15: DELEGATECALL, STATICCALLENERGY 能量消耗

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

A16: CREATE2 能量消耗

  • energyCost = 32000 + calcMemEnergy(oldMemSIze, memNeed(ost, len), 0) + 6 * [sizeInWords](#a05-sizeinwordslen)(Len)

A17: SUICIDE 能量消耗

  • energyCost = ALLOW_ENERGY_ADJUSTMENT ? ( isDeadAccount(addr) ? 25000 : 0 ) : 0