EVM Opcodes终极指南:解密以太坊虚拟机141个操作码
EVM Opcodes终极指南解密以太坊虚拟机141个操作码【免费下载链接】evm-opcodesA quick reference for EVM opcodes项目地址: https://gitcode.com/gh_mirrors/evm/evm-opcodesEVM以太坊虚拟机是以太坊区块链的核心引擎负责执行智能合约代码。本指南将全面解析EVM的141个操作码帮助开发者和区块链爱好者理解以太坊智能合约的底层运行机制。无论你是刚接触区块链开发的新手还是希望深入了解EVM工作原理的开发者这份完整指南都能为你提供清晰的操作码参考和实用的应用技巧。什么是EVM操作码EVM操作码是以太坊虚拟机执行的基本指令类似于汇编语言中的指令。每个操作码都有特定的功能如算术运算、栈操作、内存访问、存储操作等。EVM总共实现了141个操作码其中包括65个重复操作码如PUSHn、DUPn、SWAPn、LOGn等。所有栈操作数都是32字节栈的最大容量为1024项。操作码的表示方式遵循特定的符号规则例如a, b a b表示ADD操作码从栈顶取出a和b计算它们的和后将结果放回栈顶。EVM操作码分类与实例1. 算术运算类操作码算术运算类操作码用于执行基本的数学运算包括加法、减法、乘法、除法等。这类操作码是智能合约中最常用的指令之一。ADD (0x01): 加法运算消耗3 gas。栈操作:a, b a b执行(a b) mod 2²⁵⁶运算。MUL (0x02): 乘法运算消耗5 gas。栈操作:a, b a * b执行(a * b) mod 2²⁵⁶运算。SUB (0x03): 减法运算消耗3 gas。栈操作:a, b a - b执行(a - b) mod 2²⁵⁶运算。DIV (0x04): 无符号整数除法消耗5 gas。栈操作:a, b a // b注意EVM中除以0的结果为0。SDIV (0x05): 有符号整数除法消耗5 gas。栈操作:a, b a // b。2. 比较与位运算类操作码比较操作码用于比较栈上的值位运算操作码则用于执行按位逻辑运算。LT (0x10): 无符号小于比较消耗3 gas。栈操作:a, b a b结果为1真或0假。GT (0x11): 无符号大于比较消耗3 gas。栈操作:a, b a b。EQ (0x14): 等于比较消耗3 gas。栈操作:a, b a b。AND (0x16): 按位与运算消耗3 gas。栈操作:a, b a b。OR (0x17): 按位或运算消耗3 gas。栈操作:a, b a || b。XOR (0x18): 按位异或运算消耗3 gas。栈操作:a, b a ^ b。NOT (0x19): 按位非运算消耗3 gas。栈操作:a ~a。3. 栈操作类操作码栈操作类操作码用于管理EVM的栈包括入栈、出栈、复制和交换栈元素等操作。POP (0x50): 出栈操作消耗2 gas。栈操作:_anon .移除栈顶元素并丢弃。PUSH系列: PUSH1到PUSH32消耗3 gas。例如PUSH1 (0x60)将1字节值压入栈顶PUSH32 (0x7F)将32字节值压入栈顶。DUP系列: DUP1到DUP16消耗3 gas。例如DUP1 (0x80)复制栈顶元素DUP2 (0x81)复制栈中第二个元素。SWAP系列: SWAP1到SWAP16消耗3 gas。例如SWAP1 (0x90)交换栈顶两个元素SWAP2 (0x91)交换栈顶和第三个元素。4. 内存操作类操作码内存操作类操作码用于访问和修改EVM的内存空间。MLOAD (0x51): 从内存读取数据消耗3 gas加上内存扩展成本。栈操作:ost mem[ost:ost32]从内存偏移ost处读取32字节。MSTORE (0x52): 向内存写入数据消耗3 gas加上内存扩展成本。栈操作:ost, val .向内存偏移ost处写入32字节值val。MSTORE8 (0x53): 向内存写入单字节消耗3 gas加上内存扩展成本。栈操作:ost, val .向内存偏移ost处写入val的低8位。5. 存储操作类操作码存储操作类操作码用于访问和修改智能合约的持久化存储。SLOAD (0x54): 从存储读取数据消耗动态gas。栈操作:key storage[key]读取存储中键key对应的值。冷访问消耗2100 gas热访问消耗100 gas。SSTORE (0x55): 向存储写入数据消耗动态gas。栈操作:key, val .将值val写入存储中键key的位置。根据存储值的变化情况gas成本在100到20000之间变化并有可能获得gas退款。6. 控制流操作类操作码控制流操作类操作码用于控制智能合约代码的执行流程。JUMP (0x56): 无条件跳转消耗8 gas。栈操作:dst .将程序计数器设置为dst。JUMPI (0x57): 条件跳转消耗10 gas。栈操作:dst, condition .如果condition为真将程序计数器设置为dst否则继续执行下一条指令。JUMPDEST (0x5B): 跳转目标标记消耗1 gas。标识一个有效的跳转目标位置。STOP (0x00): 停止执行消耗0 gas。终止当前合约的执行。RETURN (0xF3): 返回数据消耗0 gas加上内存扩展成本。栈操作:ost, len .将内存中从ost开始的len字节数据返回给调用者。REVERT (0xFD): 回滚状态并返回数据消耗0 gas加上内存扩展成本。栈操作:ost, len .回滚当前执行的状态变化并将内存中从ost开始的len字节数据返回给调用者。7. 环境信息类操作码环境信息类操作码用于获取当前区块链和交易的相关信息。ADDRESS (0x30): 获取当前合约地址消耗2 gas。栈操作:. address(this)。BALANCE (0x31): 获取地址余额消耗动态gas。栈操作:addr addr.balance冷访问消耗2600 gas热访问消耗100 gas。ORIGIN (0x32): 获取交易发起者地址消耗2 gas。栈操作:. tx.origin。CALLER (0x33): 获取调用者地址消耗2 gas。栈操作:. msg.sender。CALLVALUE (0x34): 获取调用值消耗2 gas。栈操作:. msg.value返回以wei为单位的调用值。BLOCKHASH (0x40): 获取区块哈希消耗20 gas。栈操作:blockNum blockHash(blockNum)返回指定区块的哈希值。COINBASE (0x41): 获取当前区块矿工地址消耗2 gas。栈操作:. block.coinbase。TIMESTAMP (0x42): 获取当前区块时间戳消耗2 gas。栈操作:. block.timestamp。NUMBER (0x43): 获取当前区块号消耗2 gas。栈操作:. block.number。8. 系统操作类操作码系统操作类操作码用于执行高级系统功能如创建合约、调用其他合约、自毁合约等。CREATE (0xF0): 创建新合约消耗动态gas。栈操作:val, ost, len addr使用内存中从ost开始的len字节作为初始化代码创建新合约返回新合约地址。基础成本32000 gas加上内存扩展成本和代码存储成本。CREATE2 (0xF5): 确定性创建新合约消耗动态gas。栈操作:val, ost, len, salt addr使用指定的salt值确定性地创建新合约。CALL (0xF1): 调用其他合约消耗动态gas。栈操作:gas, addr, val, argOst, argLen, retOst, retLen success调用地址addr的合约发送val wei的价值传递内存中的参数并返回执行结果。DELEGATECALL (0xF4): 委托调用消耗动态gas。类似CALL但保留当前合约的上下文。STATICCALL (0xFA): 静态调用消耗动态gas。类似CALL但不允许修改状态。SELFDESTRUCT (0xFF): 自毁合约消耗动态gas。栈操作:addr .销毁当前合约并将所有资金发送到指定地址addr。基础成本5000 gas可能有额外成本。EVM操作码的动态Gas成本EVM操作码的Gas成本并不都是固定的许多操作码的成本会根据操作的具体情况而变化。理解这些动态成本对于编写高效的智能合约至关重要。内存扩展成本任何扩展内存使用的操作都会产生额外的Gas成本。内存扩展成本的计算公式为gas_cost (new_mem_size_words² // 512) (3 * new_mem_size_words) - C_mem(old_state)其中new_mem_size_words是操作后所需的32字节字数C_mem是内存成本函数。内存成本在使用724字节以内时呈线性增长超过这个点后成本会显著增加。存储操作成本SLOAD和SSTORE操作的成本取决于存储槽是否已经被访问过冷访问vs热访问SLOAD冷访问2100 gas热访问100 gasSSTORE根据存储值的变化情况成本在100到20000 gas之间变化并有可能获得最高4800 gas的退款账户访问成本BALANCE、EXTCODESIZE、EXTCODEHASH等操作的成本取决于账户是否已经被访问过冷访问2600 gas热访问100 gas调用操作成本CALL系列操作的成本计算比较复杂包括基础成本、访问成本、内存扩展成本和发送的Gas量。其中发送的Gas量按以下公式计算remaining_gas available_gas - base_gas all_but_one_64th remaining_gas - (remaining_gas // 64) gas_sent_with_call min(requested_gas, all_but_one_64th)EVM预编译合约除了基本操作码EVM还提供了一些预编译合约用于执行复杂的密码学运算和其他高级功能。这些预编译合约位于特定的地址通过CALL操作码调用。主要的预编译合约包括地址名称Gas成本功能描述0x01ecrecover3000椭圆曲线签名恢复0x02sha256hash动态SHA-256哈希计算0x03ripemd160hash动态RIPEMD-160哈希计算0x04dataCopy动态数据复制0x05bigModExp动态大整数模指数运算0x06bn256Add150BN256椭圆曲线加法0x07bn256ScalarMul6000BN256椭圆曲线标量乘法0x08bn256Pairing动态BN256椭圆曲线配对检查0x09blake2F动态BLAKE2密码哈希函数这些预编译合约提供了比直接使用基本操作码更高效的方式来执行复杂操作特别是密码学相关的功能。如何高效使用EVM操作码优化存储操作存储操作SSTORE/SLOAD是最昂贵的EVM操作之一。尽量减少存储操作使用内存和栈来处理临时数据。合理使用内存内存扩展成本随使用量增长而增加尤其是超过724字节后。设计智能合约时应规划好内存使用。利用预编译合约对于复杂运算如加密哈希和椭圆曲线操作使用预编译合约比手动实现更高效。优化循环和控制流EVM没有专门的循环指令使用JUMP和JUMPI实现循环时要注意效率避免不必要的迭代。注意Gas限制每个区块有Gas限制智能合约执行时不能超过这个限制。复杂操作应分解为多个交易。理解操作码Gas成本熟悉不同操作码的Gas成本优先使用低成本操作码完成相同功能。EVM操作码参考表完整的EVM操作码参考表可以在项目的README.md文件中找到其中详细列出了每个操作码的十六进制值、名称、Gas成本、栈操作和说明。以下是部分操作码的简要参考十六进制名称Gas栈操作说明00STOP0停止执行01ADD3a, ba b无符号整数加法02MUL5a, ba * b无符号整数乘法03SUB3a, ba - b无符号整数减法04DIV5a, ba // b无符号整数除法10LT3a, ba b无符号小于比较14EQ3a, ba b等于比较20SHA3动态ost, lenkeccak256(...)Keccak-256哈希计算30ADDRESS2.address(this)获取当前合约地址50POP2_anon.出栈操作56JUMP8dst.无条件跳转57JUMPI10dst, condition.条件跳转60PUSH13.uint8压入1字节值80DUP13aa, a复制栈顶元素90SWAP13a, bb, a交换栈顶两个元素F0CREATE动态val, ost, lenaddr创建新合约F1CALL动态gas, addr, ...success调用其他合约F3RETURN动态ost, len.返回数据FDREVERT动态ost, len.回滚状态并返回数据FFSELFDESTRUCT动态addr.自毁合约并发送资金完整的操作码列表和详细说明请参考项目中的README.md文件。有关动态Gas成本的详细计算方法请参考gas.md文件。总结EVM操作码是以太坊智能合约的基础构建块理解这些操作码对于编写高效、安全的智能合约至关重要。本指南介绍了EVM操作码的分类、功能和Gas成本希望能帮助你更好地理解以太坊虚拟机的工作原理。无论你是智能合约开发者、区块链研究者还是对以太坊技术感兴趣的爱好者掌握EVM操作码知识都将为你的区块链之旅提供坚实的基础。随着以太坊生态系统的不断发展EVM也在不断进化新的操作码和功能会不断被引入建议持续关注EVM的最新发展。要开始使用EVM操作码进行开发可以通过以下命令克隆项目仓库git clone https://gitcode.com/gh_mirrors/evm/evm-opcodes在项目中你可以找到完整的操作码参考表和Gas成本说明帮助你更深入地学习和应用EVM操作码。【免费下载链接】evm-opcodesA quick reference for EVM opcodes项目地址: https://gitcode.com/gh_mirrors/evm/evm-opcodes创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考