从脚本到程序:智能批处理如何演进链上执行

  • Biconomy
  • 发布于 15小时前
  • 阅读 36

本文深度对比了以太坊链上执行脚本工具 Weiroll 与新兴标准 ERC-8211。Weiroll 作为一个轻量级虚拟机支持简单的调用链,而 ERC-8211 通过声明式智能批处理提供了更强的参数注入、内联约束和跨链支持,代表了未来 DeFi 执行的发展方向。

From Scripts to Programs: How Smart Batching Evolves On-Chain Execution

一份关于 Weiroll 和 ERC-8211 的技术对比——以及为什么声明式执行是 DeFi 的未来。


如果你曾尝试在单个交易中将一次兑换(swap)链接到一次借贷存款,你肯定已经知道问题所在。你签署了一个批处理指令,上面写着“将 100 USDC 兑换为 WETH,然后向 Aave 提供 0.05 WETH”。等交易落地时,兑换仅返回了 0.0495 WETH。你硬编码的 0.05 金额导致失败。批处理发生回滚(revert)。你的 Gas 白白消耗了。

这并非小众的边缘案例。这是当今以太坊上多步 DeFi 操作的默认体验。兑换输出取决于价格影响、滑点和 MEV。借贷提取取决于波动的份额率。跨链桥接交付带有不可预测的费用。每一个触及实时状态的参数,在你签署的那一刻都变成了一种猜测。

两个项目从根本不同的角度解决了这个问题。Weiroll 是 2021 年的先驱,它引入了一个轻量级虚拟机,用于在 EVM 上链接合约调用。ERC-8211 是由 Biconomy 和以太坊基金会提出的 2026 年标准轨道提案,它引入了“智能批处理”——一种声明式编码,其中每个参数都描述了如何在执行时获取其值以及该值必须满足什么条件

本文将详细对比它们:它们在底层是如何工作的,它们在哪里分道扬镳,以及为什么这种差异对于任何构建或使用 DeFi 的人来说都至关重要。


Weiroll:先驱者

Weiroll 是超越简单 Multicall 的最早的严肃尝试之一。Multicall 让你能够批量处理独立的调用,而 Weiroll 让你能够链接它们——调用 A 的返回值可以成为调用 B 的输入。通过这种方式,它在以太坊开发工具包中建立了一个全新的原语:可组合的链上脚本。

工作原理

Weiroll 是一个微型链上虚拟机。你给它两样东西:一个命令(commands)数组(每个命令打包成 32 字节)和一个状态(state)值数组(你的工作寄存器)。虚拟机逐一运行这些命令。每个命令说明:“在某个合约上调用此函数,从这些状态槽中提取输入,将输出写入那个状态槽。”

命令 (bytes32):
┌───────┬─┬───────────┬─┬───────────────────────────────────────┐
│  sel  │f│    in     │o│              target                   │
└───────┴─┴───────────┴─┴───────────────────────────────────────┘
  4字节    1  6字节     1         20字节地址
  选择器   标志 索引    输出

它的美妙之处在于其简单性。在大约 200 行 Solidity 代码中,Weiroll 可以链接任意合约调用,在它们之间传递返回值,并处理定长和变长参数。weiroll.js TypeScript SDK 为开发者提供了一个 Planner 抽象:

const planner = new weiroll.Planner();
const wethOut = planner.add(router.exactInputSingle(usdc, weth, 500, amount, 0));
planner.add(aavePool.supply(weth, wethOut, self, 0));
const { commands, state } = planner.plan();

Planner 处理状态槽分配,因此开发者不必考虑寄存器索引。一些生产系统已经采用了 Weiroll,包括 Enso Finance(用于其“统一 DeFi API”)和 Royco Protocol(用于链上交易“配方”)。

Weiroll 的闪光点

Gas 效率。 Weiroll 的编码极其紧凑。一个命令就是一个 bytes32CommandBuilder 库使用汇编级的内存操作,利用 identity 预编译进行内存复制,并尽可能避免动态分配。对于不带额外安全逻辑的原始操作链,很难在 Gas 消耗上超越它。

最小化攻击面。 整个虚拟机大约只有 200 行 Solidity 代码。CommandBuilder 库还有 150 行。审计代码的工作量非常小,且现有代码非常直观。ChainSecurity 的审计结论是,该代码库在功能正确性和内存一致性方面提供了“良好的安全水平”。小巧的体积也意味着漏洞隐藏的地方更少。

真正的通用性。 Weiroll 对你链接的内容没有偏见。DeFi 兑换、NFT 铸造、治理投票、任意合约交互——只要它有函数选择器,Weiroll 就能调用它并将输出传输下去。它支持 DELEGATECALLCALLSTATICCALL带值的 CALL,涵盖了所有 EVM 调用类型。子计划机制甚至可以处理闪电贷风格的回调,在这种情况下,嵌套序列必须在回调框架内执行。

经过生产验证。 Weiroll 并非理论。Enso Finance 通过它处理真实的 DeFi 流程。Royco Protocol 使用它来定义链上激励“配方”。这些不是玩具级的部署——它们处理真实的价值,并经受住了主网敌对环境的考验。在评估任何链上原语时,这种生产记录至关重要。

极低的采用门槛。 任何能够 delegatecall 的合约都可以使用 Weiroll 虚拟机。无需实现接口、注册模块或与账户抽象标准集成。对于只需要操作链接而不需要其他的团队来说,Weiroll 的不拘礼节是一个特性。

它的局限性

Weiroll 是作为通用的管道构建的,它的表现也确实如此。没有分支,没有循环,没有内置的安全检查。如果兑换返回的结果少于你的预期,下一个调用要么成功要么回滚——如果不部署自定义断言合约并将其串联到命令链中,就无法断言“输出必须至少为 X”。

链上编码是不透明的。bytes32[] 命令数组和 bytes[] 状态数组不携带任何语义信息。审计员检查 calldata 时只能看到打包的字节和状态槽索引。确定一个 Weiroll 程序到底做了什么需要解码每个命令、交叉引用 ABI 并脑补模拟状态变化。审计过 Enso-Weiroll 实现的 ChainSecurity 将“命令效果评估的复杂性”列为该设计固有的根本顾虑。

还有跨链?Weiroll 对此没有概念。它是一个单交易、单链的虚拟机。如果你想跨链协同,你需要自己构建编排工作。

这些不是设计的失败——它们是范围界定的结果。Weiroll 旨在成为一个极简、高效的操作链接器,它成功了。问题在于,这个范围是否足以满足 2026 年生态系统的需求。


ERC-8211:智能批处理

ERC-8211 从一个不同的前提开始。它没有问“我们如何高效地链接函数调用?”,而是问:“一个 DeFi 执行计划实际上需要声明什么?”

根据该标准的作者,答案是三件事:

  1. 如何获取每个值——不仅仅是值是什么,还包括如何在执行时获得它。
  2. 该值必须满足什么条件——内联约束,如果违反则使整个批处理回滚。
  3. 如何路由该值——它是变成调用目标、ETH 金额还是 calldata。

三个原语

运行时参数注入。 每个参数都带有一个“获取器类型”(fetcher type),告诉执行器如何在链上解析该值:

  • RAW_BYTES——一个字面值,在编码时已知。
  • STATIC_CALL——任意链上读取(预言机价格、池状态等任何内容)。
  • BALANCE——ERC-20 或原生余额查询。

你不再编写 supply(0.05 WETH) 并祈祷成功,而是编写 supply(BALANCE(WETH))。执行器在执行时调用 IERC20(WETH).balanceOf(self) 并获得精确的数字。

前置和后置断言。 每个解析出的值都可以带有内联约束——EQGTELTEIN——这些约束在值被路由之前会在链上进行检查。target = address(0) 的条目变成了一个谓词条目:一个纯布尔门控,如果条件失败则回滚整个批处理。

这就是你在不编写 Solidity 的情况下获得 MEV 保护的方式:断言兑换输出大于或等于你的最低可接受金额。如果夹心攻击将输出压缩到该阈值以下,批处理将原子化地回滚。无需自定义合约,无需审计周期。

多交易上下文。 一个共享的 Storage 合约允许条目写入值,供后面的条目——甚至随后的 UserOperations——读取。数据在步骤之间流动,无需自定义合约。

编写过程示例

TypeScript SDK 将高层意图编译为链上编码:

const batch = smartBatch([\
  swap({ from: WETH, to: USDC, amount: fullBalance() }),\
  predicate({ balance: gte(USDC, account, 2500e6) }),\
  supply({ protocol: "aave", token: USDC, amount: fullBalance() }),\
  stake({ token: aUSDC, amount: fullBalance() }),\
]);

四个步骤。每个金额都动态解析。内联谓词确保兑换返回了足够的资金。没有硬编码值。没有残留的碎屑(dust)。不需要 Solidity。


它们的分歧点

可读性:打包字节 vs. 自描述数据

Weiroll 的链上表示是一个打包的二进制数组。它紧凑且 Gas 效率高,但理解它需要专门的工具。向用户显示 Weiroll 交易的钱包会显示……一个十六进制大对象(blob)。

ERC-8211 的编码是结构化数据。每个 ComposableExecution 条目包含类型化字段:获取器类型、路由目的地、约束数组。钱包或区块浏览器仅通过编码就能重构批处理的意图——无需外部 ABI 查找,无需启发式分析。

这听起来可能像是一个审美问题。其实不然。可读性直接决定了自动化工具是否能分析批处理,钱包是否能显示有意义的预览,以及审计员是否能验证安全性。编码本身携带的信息越多,终端用户对不透明工具的信任就越少。

静态分析:能否在不运行的情况下验证它?

Weiroll 程序是自定义虚拟机的字节码。要静态分析一个程序,你需要一个能够理解命令编码、状态数组变化以及每个目标合约 ABI 的符号执行引擎。这是可以实现的——人们一直在为 EVM 字节码构建符号分析器——但这并不容易,而且编码中缺乏语义元数据意味着分析器必须从低级操作中推断意图。ChainSecurity 审计了 Enso-Weiroll 的实现,指出“命令效果评估的复杂性”是设计中固有的基本顾虑。

ERC-8211 批处理是声明式元数据。每个参数都会预先宣布其解析策略和约束。静态分析器可以检查 InputParam 并立即知道:“这会读取发送者的 USDC 余额,将其路由到第三个 calldata 位置,并断言它必须 ≥ 2500e6。”无需推断。意图就在编码中。

这开启了一类新的工具:意图级静态分析。不仅仅是“这段字节码会回滚吗?”,而是“批处理声明的意图是否符合用户的实际目标?”中继器、捆绑器(bundler)和 AI Agent 都能直接从中受益。

DeFi 优先 vs. 通用

Weiroll 是一个通用的操作链接器。它可以链接任何合约调用——DeFi 兑换、NFT 铸造、DAO 治理、自定义协议交互——而不在意这些调用做了什么。这种通用性确实很有价值:Weiroll 可以作为任何链上工作流的通用“粘合”层,其中心性意味着它永远不会受限于设计者选择包含的原语。如果你能将其表达为一系列合约调用,Weiroll 就能执行它。

权衡之处在于,每个 DeFi 特有的需求(余额查询、滑点检查、预言机门控)都需要部署自定义辅助合约并对其进行审计。Weiroll 给你管道;你得自己装配件。

ERC-8211 做了相反的赌注。它是从头开始为 DeFi 构建的。BALANCE 获取器、约束系统、谓词条目、Storage 合约——这些都是过去五年中真实 DeFi 流程所渴求的特定原语,被直接编入标准编码中。虽然 ERC-8211 技术上可以调用任何智能合约(它不局限于 DeFi),但其设计选择刻意针对 DeFi 需求最旺盛的模式进行了优化。

考虑在两者中实现“发送我的全部代币余额并带有滑点保护”需要什么:

Weiroll:

  1. 部署一个辅助合约,调用 balanceOf 并返回余额。
  2. 部署一个断言合约,比较两个值并在检查失败时回滚。
  3. 链接:辅助调用 → 兑换调用 → 断言调用 → 供应调用。
  4. 审计这两个自定义合约。
  5. 为所有中间值手动管理状态槽。

ERC-8211:

  1. 将兑换金额的获取器设置为 BALANCE
  2. 向兑换输出参数添加一个 GTE 约束。
  3. 将供应金额的获取器设置为 BALANCE
  4. 完成。无需部署。无需审计自定义合约。

对于构建通用工具或非 DeFi 工作流的团队,Weiroll 的无偏见设计可能仍然更合适。对于 DeFi 特有的流程——占当今多步链上执行的绝大部分——ERC-8211 消除了一整类基础设施工作。

跨链:缺失 vs. 原生

这也许是最显著的差异。

Weiroll 没有跨链模型。它是一个单链虚拟机。如果你需要一个多链流程——比如在 Base 上平仓并在以太坊上重新部署——你需要为每个链构建单独的 Weiroll 程序,并在外部进行编排。

ERC-8211 将跨链编排视为头等大事。用户签署一个涵盖多个链上批处理的单个 Merkle 根。每个链本地的批处理独立执行。以太坊侧的批处理包含基于跨链状态的谓词条目门控:“仅在我的 WETH 余额超过 2 ETH 时执行此操作”(意味着来自 Base 的桥接已送达)。

该规范明确表示对互操作层保持可信中立。谓词观察的是状态,而不是机制。无论桥接是 Optimism 的原生桥、Across、ERC-7683 还是 LayerZero,批处理只是等待余额出现。这是一种强大的关注点分离:执行计划不在乎资产如何到达,只在乎它们已经到达。

安全模型:隐式 vs. 显式

Weiroll 的安全故事既有真正的优势,也有结构性的局限。从积极的一面来看,其微小的代码库(约 350 行 Solidity)意味着相对较小的攻击面。ChainSecurity 的审计确认了功能正确性和内存一致性的“高安全性”。执行模型的简单性——顺序命令、无分支、无重入模式——使得虚拟机本身是可预测的。而且 Weiroll 支持所有四种 EVM 调用类型,因此开发者在 DELEGATECALL 过于宽松时,可以选择 STATICCALL 进行只读操作或 CALL 进行外部交互。(例如,Enso 的生产部署完全禁用了 DELEGATECALL,仅运行 CALL。)

结构性限制在于 Weiroll 没有内置的验证层。所有安全性必须来自被调用的合约本身或自定义包装合约。编码不包含关于程序员期望保持哪些不变性的信息。这把安全负担完全压在了开发者身上,并使得外部工具(钱包、捆绑器、审计员)在缺乏深度上下文的情况下更难推敲批处理的安全性。

ERC-8211 反转了这一模型。它使用标准的 CALL 语义,并将内联约束作为一等安全机制。每个解析出的值在路由之前都会根据其谓词进行验证。安全不变性是编码本身的一部分——对钱包可见,可被工具分析,可在链上验证。

这种转变——从“安全是开发者的问题”到“安全被编码在批处理中”——可以说是 ERC-8211 最重要的设计决策。它并不能取代谨慎开发的需要,但它提供了一个结构化的保护层,而这在安全性完全依赖外部的系统中是缺失的。


Gas 问题

Weiroll 每个命令更轻量,这并非微不足道的优势。打包的 bytes32 命令对比结构化的 ComposableExecution 结构体——Weiroll 在原始编码大小和 calldata 成本上具有压倒性优势。对于 calldata 压缩是主要成本因素的 L2 链,或者对于安全检查由目标合约处理的简单操作链,Weiroll 的编码效率直接转化为更低的成本。如果你链接的三个调用不需要内联断言,Weiroll 几乎肯定会更便宜。

对于生产级 DeFi 流程,计算方式发生了变化。一旦你添加了余额断言、滑点保护或预言机门控(这是大多数真实流程所需要的),你就在 Weiroll 中部署并调用了额外的辅助合约。这些跨合约调用增加了 Gas,抵消了编码优势。

ERC-8211 的内联约束避免了安全检查的跨合约调用开销。对于具有适当安全性的生产级 DeFi 流程,总 Gas 成本具有竞争力。正确的视角不是“哪个更便宜?”,而是“哪个能在同样的 Gas 下给你更多?”——对于需要运行时解析和安全保证的 DeFi 流程,ERC-8211 的单位 Gas 价值主张非常强大。


兼容性与以账户为中心的愿景

Weiroll 的兼容性模型很简单:如果你的合约可以 delegatecall 该虚拟机,你就可以使用它。这很有效,且其简单性是快速集成的优势。但它对账户层是不可知的——Weiroll 不知道也不在乎它是在 ERC-4337 智能账户、ERC-7702 委托 EOA 还是原始合约中运行。集成者需要构建自己的适配器。

ERC-8211 采取了根本不同的方法。它是设计上以账户为中心的——该标准不仅定义了编码,还定义了一个单一接口(IComposableExecution),并带有适用于所有主流智能账户架构的规范化集成模式:

  • ERC-7579: 执行器模块——通过标准模块生命周期进行安装。
  • ERC-6900: 插件——通过 manifest 注册 executeComposable
  • Native: 直接继承 IComposableExecution
  • ERC-7702: 委托目标——让 EOA 在不部署智能账户的情况下获得可组合执行能力。

它还兼容 ERC-4337 智能账户、EIP-5792 的 wallet_sendCalls 以及 ERC-7683/7786 互操作层。

为原生账户抽象做准备:EIP-8141

当你观察以太坊本身的发展方向时,这种以账户为中心的定位变得更加重要。EIP-8141——由 Vitalik Buterin、lightclient 和 ERC-4337 团队共同撰写的 Frame Transaction 提案——引入了一种新的交易类型(0x06),使账户抽象成为一等协议特性。Frame 交易不再依赖单一的 ECDSA 签名,而是将验证、执行和 Gas 支付分解为独立的“frame”,每个 frame 由任意 EVM 代码执行。

在 EIP-8141 之下,每个账户都变得可编程。验证可以使用任何加密方案(包括后量子加密)。Gas 可以由第三方支付或以 ERC-20 代币支付。执行 frame 在可配置的调用者上下文中运行(ENTRY_POINTSENDERDEFAULT)。

ERC-8211 明确设计为在该架构中作为执行有效载荷运行。Frame 交易的 SENDER 模式 frame 可以调用发送者账户上的 executeComposable(),运行一个带有运行时解析参数和内联约束的完整智能批处理——所有这些都在以太坊的原生交易格式内完成。谓词模型自然地映射到 Frame 交易:VERIFY frame 处理授权,而 SENDER frame 执行可组合批处理。无需捆绑器基础设施,无需内存池(mempool)变通方案。原生的协议级账户抽象,以智能批处理作为执行层。

这并非投机性的兼容性。ERC-8211 的 PR (#1638) 将 EIP-8141 列为兼容目标,并且 lightclient(EIP-8141 的共同作者)直接审阅了 ERC-8211 规范。这两个标准在设计时就相互意识到了对方的存在。

Weiroll 作为 2021 年的通用虚拟机,早于这一整套账户抽象技术栈,并且与这些标准没有正式关系。它当然可以被包装进各自的适配器中,但包装工作留给了集成者去完成。

其含义显而易见:ERC-8211 不仅仅是在解决当今的 DeFi 执行问题。它正在将可组合执行定位为以太坊原生账户抽象未来的头等公民。


大局观

Weiroll 理应获得比现在更多的赞誉。在 Weiroll 之前,以太坊执行模型既简单又受限:一个交易,一个函数调用。Multicall 通过批量处理独立调用改善了这一点,但它无法表达它们之间的依赖关系。Weiroll 打破了那个障碍。它证明了一个轻量级的链上虚拟机可以在任意合约调用之间穿梭返回值,从而用单个操作创建出可组合的程序。它以极简的代码、令人印象深刻的 Gas 效率实现了这一点,并已发布到生产环境。Enso、Royco 等公司在此基础上建立了真实的业务。Weiroll 引入的“链上脚本”概念影响了随后出现的每一个可组合执行系统。

对于那些重视原始简单性的用例——极简的虚拟机、极致的 Gas 效率、对链接内容零偏见——Weiroll 仍然是一个优秀的工具。它可能会继续为围绕它构建的系统以及需要一个轻量、通用的执行层而不需要正式标准重量感的团队提供服务。

但周围的环境已经发生了变化。DeFi 默认是多链的。账户抽象在多个竞争标准中已经成熟,并正通过 EIP-8141 走向原生协议支持。AI Agent 正作为链上参与者出现,它们需要可验证、受约束的执行。2026 年的需求与 2021 年根本不同。

ERC-8211 吸收了 Weiroll 的核心见解——通过数据依赖链接调用——并将其包装在一个为当今 DeFi 的运作方式以及以太坊未来的发展方向而设计的系统中:

  • 可读,因为编码描述的是意图,而不仅仅是操作。

  • 可分析,因为获取器类型和约束是声明式元数据。

  • 默认安全,因为断言是内联的,而不是事后补救。

  • DeFi 原生,因为余额查询、滑点保护和预言机门控是一等原语。

  • 原生跨链,因为谓词门控和 Merkle 授权处理跨链协调而无需自定义合约。

  • 以账户为中心,因为它与每个主要的智能账户标准集成,并为以太坊的原生账户抽象未来 (EIP-8141) 而设计。

  • 互操作性强,因为一种编码、一个接口,到处通用。

    • *

ERC-8211 处于草案(Draft)状态。规范可在 erc8211.com 查看,ERC 拉取请求位于 ethereum/ERCs #1638 。Weiroll 的源码位于 github.com/weiroll/weiroll ,其 JS SDK 位于 weiroll.github.io/weiroll.js

  • 原文链接: blog.biconomy.io/from-sc...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Biconomy
Biconomy
江湖只有他的大名,没有他的介绍。