{"content":{"title":"EIP7511 最小代理合约解析","body":"# EIP7511 最小代理合约解析\r\n\r\n## 备注\r\n\r\n时间：2023 年 9 月 9 日\r\n\r\n作者：[33357](https://github.com/33357)\r\n\r\n## 正文\r\n\r\nEIP7511 优化了 EIP1167，实现了更加节省 GAS 的代理合约。提案地址：https://eips.ethereum.org/EIPS/eip-7511\r\n\r\n想要从字节码的层面理解智能合约，就必须先了解 `堆栈`、`内存`、`存储` 、`OPCODE` 等概念，这里推荐 https://www.evm.codes/ 和 https://www.wtf.academy/en/evm-opcodes-101 了解。\r\n\r\n### 最小代理合约字节码\r\n\r\n#### 字节码\r\n```\r\n365f5f375f5f365f73bebebebebebebebebebebebebebebebebebebebe5af43d5f5f3e5f3d91602a57fd5bf3\r\n```\r\n\r\n#### 分析\r\n- 复制 CALLDATA 到内存\r\n\r\n| 执行位置 | 字节码 | 操作名 | 堆栈 | 内存 | 说明 ｜\r\n|----|----|--------------|---------|----------|----------------------------------------------|\r\n| 00 | 36 | CALLDATASIZE | cds     |          | 将 calldatasize 计为 cds，并压入堆栈 |\r\n| 01 | 5f | PUSH0        | 0 cds   |          | 将 0 压入堆栈 |\r\n| 02 | 5f | PUSH0        | 0 0 cds |          | 将 0 压入堆栈 |\r\n| 03 | 37 | CALLDATACOPY |         | calldata | 将 0 - cds 的 calldata 复制到从 0 开始的内存空间 |\r\n\r\n- DELEGATECALL\r\n\r\n| 执行位置 | 字节码 | 操作名 | 堆栈 | 内存 | 说明 ｜\r\n|----|---------|----------------|-----------------------|----------|---------------------------------------------------------------|\r\n| 04 | 5f      | PUSH0          | 0                     | calldata | 将 0 压入堆栈 |\r\n| 05 | 5f      | PUSH0          | 0 0                   | calldata | 将 0 压入堆栈 |\r\n| 06 | 36      | CALLDATASIZE   | cds 0 0               | calldata | 将 calldatasize 计为 cds，并压入堆栈 |\r\n| 07 | 5f      | PUSH0          | 0 cds 0 0             | calldata | 将 0 压入堆栈 |\r\n| 08 | 73bebe. | PUSH20 0xbebe. | 0xbebe. 0 cds 0 0     | calldata | 将 20 个字节的数据压入堆栈 |\r\n| 1d | 5a      | GAS            | gas 0xbebe. 0 cds 0 0 | calldata | 将 gas 压入堆栈 |\r\n| 1e | f4      | DELEGATECALL   | suc                   | calldata | 将 0 - cds 的内存数据作为参数执行 0xbebe. 地址的代码，将执行是否成功计为 suc，并压入堆栈 |\r\n\r\n- 复制 RETURNDATA 到内存\r\n\r\n| 执行位置 | 字节码 | 操作名 | 堆栈 | 内存 | 说明 ｜\r\n|----|----|----------------|-----------------|------------|--------------------------------------------|\r\n| 1f | 3d | RETURNDATASIZE | rds suc     | calldata   | 将 returndatasize 计为 rds，并压入堆栈 |\r\n| 20 | 5f | PUSH0          | 0 rds suc   | calldata   | 将 0 压入堆栈 |\r\n| 21 | 5f | PUSH0          | 0 0 rds suc | calldata   | 将 0 压入堆栈 |\r\n| 22 | 3e | RETURNDATACOPY | suc         | returndata | 将 0 - rds 的 returndata 复制到从 0 开始的内存空间 |\r\n\r\n- 返回数据或拒绝交易\r\n\r\n| 执行位置 | 字节码 | 操作名 | 堆栈 | 内存 | 说明 ｜\r\n|----|------|----------------|----------------|------------|---------------------------------|\r\n| 23 | 5f   | PUSH0          | 0 suc          | returndata | 将 0 压入堆栈 |\r\n| 24 | 3d   | RETURNDATASIZE | rds 0 suc      | returndata | 将 returndatasize 计为 rds，并压入堆栈 |\r\n| 25 | 91   | SWAP2          | suc 0 rds      | returndata | 将堆栈第一个元素和第三个元素互换 |\r\n| 26 | 602a | PUSH1 0x2a     | 0x2a suc 0 rds | returndata | 将 1 个字节的数据压入堆栈 |\r\n| 27 | 57   | JUMPI          | 0 rds          | returndata | 如果 suc 不为 0 则执行位置跳转到 2a|\r\n| 29 | fd   | REVERT         |                |            | 返回 0 - rds 的内存数据并回滚状态 |\r\n| 2a | 5b   | JUMPDEST       | 0 rds          | returndata | 跳转标记 ｜\r\n| 2b | f3   | RETURN         |                |            | 返回 0 - rds 的内存数据 |\r\n\r\n### 部署最小代理合约字节码\r\n\r\n部署合约字节码需要了解 `initcode` 和 `runtimecode` 的区别。\r\n\r\n部署合约时会先执行 `initcode`，`initcode` 执行后返回的结果就是 `runtimecode`，真正被部署在合约上的字节码。\r\n\r\n#### 字节码\r\n\r\n```\r\n602c8060095f395ff3365f5f375f5f365f73bebebebebebebebebebebebebebebebebebebebe5af43d5f5f3e5f3d91602a57fd5bf3\r\n```\r\n\r\n#### 分析\r\n\r\n- 部署代码\r\n\r\n| 执行位置 | 字节码 | 操作名 | 堆栈 | 内存 | 说明 |\r\n|----|------|----------|------------|-|----------------------------------------------|\r\n| 00 | 602c | PUSH1 2c | 2c         | | 将 1 个字节的数据压入堆栈 |\r\n| 02 | 80   | DUP1     | 2c 2c      | | 复制堆栈第一个元素并压入堆栈 |\r\n| 03 | 6009 | PUSH1 09 | 09 2c 2c   | | 将 1 个字节的数据压入堆栈 |\r\n| 05 | 5f   | PUSH0    | 0 09 2c 2c | | 将 0 压入堆栈 |\r\n| 06 | 39   | CODECOPY |            | 365f5f375f5f365f73be...be5af43d5f5f3e5f3d91602a57fd5bf3 | 将 09 - 2c 的 code 复制到从 0 开始的内存空间 |\r\n| 07 | 5f   | PUSH0    | 0 2c       | 365f5f375f5f365f73be...be5af43d5f5f3e5f3d91602a57fd5bf3 | 将 0 压入堆栈 |\r\n| 08 | f3   | RETURN   |            | 365f5f375f5f365f73be...be5af43d5f5f3e5f3d91602a57fd5bf3 | 将 0 - 2c 的内存数据返回 |\r\n\r\n## 原文发布在 <https://github.com/33357/smartcontract-apps> 这是一个面向中文社区，分析市面上智能合约应用的架构与实现的仓库。欢迎关注开源知识项目！"},"author":{"user":"https://learnblockchain.cn/people/3877","address":"0x1f2479ee1b4aFE789e19D257D2D50810ac90fa59"},"history":null,"timestamp":1696476648,"version":1}