当前位置: 首页 > news >正文

Solidity 合约高级应用 8| 简单字节码合约 (Simple Bytecode Contract)

在 Solidity 中,合约最终会被编译为 EVM 字节码部署到链上。理解字节码有助于深入掌握合约的底层行为、优化 Gas 以及编写极简合约。下面将介绍字节码的基本构成,并展示如何编写一个“简单字节码合约”——即通过直接操作字节码实现最小功能的合约。

1. 合约字节码的构成

一个合约的字节码分为两部分:

  • 创建时字节码(Init Code / Constructor Bytecode):在部署交易中执行的代码。它负责初始化状态变量、执行构造函数逻辑,并最终返回运行时字节码(Runtime Bytecode)。创建时字节码执行完毕后,其返回的代码将永久存储在链上,成为合约的代码。
  • 运行时字节码(Runtime Bytecode):存储在链上、在每次调用合约时执行的代码。它包含了合约的函数选择器、各函数的实现逻辑等。

例如,一个简单的存储合约:

pragma solidity ^0.8.0; contract SimpleStorage { uint256 public storedData; function set(uint256 x) public { storedData = x; } function get() public view returns (uint256) { return storedData; } }

编译后,你会得到两段字节码:创建时字节码(包含构造函数和返回运行时字节码的逻辑)和运行时字节码(包含setget的实现)。

2. 极简运行时字节码:仅返回一个值

如果我们想要一个最简单的合约,它只做一件事:每次调用都返回一个固定的数字(比如42),那么它的运行时字节码可以非常短。

2.1 用 Solidity 实现
pragma solidity ^0.8.0; contract SimpleReturn { function always42() external pure returns (uint256) { return 42; } }

编译后,这个合约的运行时字节码大约有几十个字节,包含了函数选择器、跳转表等。但我们可以做得更小:直接编写一个合约,使得任何调用(无论 calldata 是什么)都返回42

2.2 使用内联汇编编写极简运行时字节码

我们可以直接在 Solidity 合约的构造函数中返回我们自定义的运行时字节码。下面的合约在部署时不会包含任何 Solidity 生成的函数,而是直接返回一段手写的汇编字节码:

pragma solidity ^0.8.0; contract TinyBytecode { constructor() { // 在构造函数中返回自定义的运行时字节码 bytes memory runtimeCode = hex"600a600c600039600a6000f3602a60005260206000f3"; assembly { return(add(runtimeCode, 0x20), mload(runtimeCode)) } } }

但这段代码比较晦涩。更清晰的方式是使用 Yul 对象直接编写字节码。实际上,我们可以创建一个只包含运行时字节码的“原始”合约,用createcreate2部署。这里给出一个完整的 Yul 示例:

object "SimpleReturn" { code { // 部署时代码:直接返回 runtime 对象 datacopy(0, dataoffset("runtime"), datasize("runtime")) return(0, datasize("runtime")) } object "runtime" { code { // 运行时:永远返回 42 (0x2a) // 将 0x2a 放入内存,然后返回 mstore(0, 0x2a) return(0, 0x20) } } }

将上述 Yul 编译后,可以得到一个极小的合约:它的运行时字节码为602a60005260206000f3。解释一下:

  • 602a:将0x2a(42) 压入栈。
  • 600052:将栈顶值(42)存到内存地址 0。
  • 6020:将0x20(32) 压入栈(返回值长度)。
  • 6000:将0压入栈(返回值起始内存地址)。
  • f3RETURN,从内存返回数据。

所以任何调用该合约的交易,无论 calldata 是什么,都会返回0x0000...002a(即 32 字节的 42)。

3. 直接部署原始字节码

如果你已经有一个编译好的运行时字节码(例如上面得到的602a60005260206000f3),你可以通过一个“部署器”合约来部署它,或者直接使用create操作码。

3.1 使用 Solidity 的create部署
pragma solidity ^0.8.0; contract Deployer { function deployTiny() external returns (address) { bytes memory runtimeCode = hex"602a60005260206000f3"; address addr; assembly { addr := create(0, add(runtimeCode, 0x20), mload(runtimeCode)) } require(addr != address(0), "deploy failed"); return addr; } }

调用deployTiny会创建一个新合约,其代码就是602a60005260206000f3。然后你可以调用该合约(用任意 calldata),它总是返回 42。

3.2 直接通过交易部署

你也可以手动构造一个部署交易,其data字段包含创建时字节码。创建时字节码需要包含将运行时字节码返回的逻辑。例如,使用如下 Yul 对象生成创建时字节码:

object "Creator" { code { // 复制运行时字节码到内存并返回 datacopy(0, dataoffset("runtime"), datasize("runtime")) return(0, datasize("runtime")) } object "runtime" { code { // 运行时字节码(和上面一样) mstore(0, 0x2a) return(0, 0x20) } } }

编译后得到创建时字节码,直接作为交易的data发送,即可部署出只返回 42 的合约。

4. 为什么需要简单字节码合约?

  • 最小化合约:用于特定目的(如预言机返回固定值、多签钱包的 fallback 函数)可以大大降低 Gas 成本。
  • 教学用途:帮助理解 EVM 执行模型。
  • 高级优化:某些协议需要极小的代理合约(如 EIP-1167 最小代理合约),其字节码通常只有 45 字节左右。

5. 风险与注意事项

  • 可读性差:直接操作字节码容易出错且难以审计。
  • 函数选择器缺失:上述极简合约没有函数选择器逻辑,任何调用都会返回相同结果。如果需要多个函数,必须手动实现跳转表。
  • 存储与内存:手动管理内存和存储需谨慎,避免破坏合约状态。
  • 部署方式:使用create部署时,要确保字节码正确,否则可能部署失败或产生意外行为

6. 扩展:EIP-1167 最小代理合约

一个更实用的“简单字节码合约”是 EIP-1167 最小代理,它通过极少的字节码将调用转发给另一个实现合约。其运行时字节码只有 45 字节:

363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3

7. 总结

简单字节码合约展示了 Solidity 和 EVM 的底层能力。通过直接编写或部署极简的运行时字节码,可以创建功能单一但 Gas 极低的合约。理解字节码结构不仅有助于优化,也能帮助开发者深入理解合约的执行过程。在实际开发中,大多数情况下应使用高级语言(Solidity、Yul)确保安全,但掌握底层知识是成为高级开发者的重要一步。

http://www.jsqmd.com/news/457974/

相关文章:

  • 聊聊2026年中润科技,其防蚊贴和安睡贴产品靠谱吗 - 工业品网
  • AI学习(三)openclow启动(2)2026/03/05
  • openGauss数据库源码解析系列文章——存储引擎源码解析(一)
  • 2026年知名的吸塑泡壳品牌推荐:PP吸塑泡壳/PVC吸塑泡壳用户口碑认可参考(高评价) - 品牌宣传支持者
  • 2026年河南高性价比的面粉加工设备工厂好用吗,哪家比较靠谱 - 工业品牌热点
  • 山东钢格栅厂家口碑排行,推荐几家性价比高的 - 工业设备
  • 第三课 Hadoop 三大核心组件笔记
  • OpenClaw + Docker + MiniMax 本地养“龙虾”方案
  • 2026最新双组份中空玻璃胶厂家top5权威推荐!国内优质双组份中空玻璃胶权威厂商榜单发布 - 十大品牌榜
  • 用股票免费API快速搭建量化策略
  • 具身智能成两会热词,全球最小电缸量产,EAI提速,VLA融资破纪录
  • 真空电炉小型企业分离装置费用多少,值得合作的品牌有啥 - myqiye
  • 2026年值得推荐的粮库门窗生产商,个性化定制服务靠谱吗 - 工业推荐榜
  • TI C2000内部控制算法,包含零极点控制,PID,锁相环,MPPT最大功率点跟踪等
  • 三防布定做厂家
  • PID学习笔记(江协科技同款)
  • 计算机A类国际会议有哪些?
  • SSH暴力破解与弱口令攻击分析:一次由弱口令引发的测试服沦陷
  • 基于Docker和Gitea自建Git仓库镜像服务实践
  • 湖南本地GEO推广服务多少钱,湖南讯灵智能科技值得推荐吗 - mypinpai
  • AI智能名片系统有哪些功能?全面使用介绍
  • 【现代机器人学】一、位形空间(Configuration Space)
  • 短剧系统平台开发:前端后端技术选型与部署
  • 打破芯片壁垒:基于Docker与K8s的GB28181/RTSP异构AI视频平台架构实战
  • 关于 提取git所有提交日志导出到txt文本的 解决方法
  • 地球系统模式(CESM)应用
  • 光伏充电系统建模手记:当PO法遇上三阶段充电
  • DO-254通读--前言执行摘要目录
  • IACheck AI报告文档审核:驱动高端制造合规管理报告审核升级的新引擎
  • npm安装OpenClaw中Git报错解决方法