4 个版本
0.1.3 | 2023 年 11 月 13 日 |
---|---|
0.1.2 | 2023 年 11 月 10 日 |
0.1.1 | 2023 年 10 月 20 日 |
0.1.0 | 2023 年 9 月 18 日 |
119 在 #evm 中
每月 44 次下载
17KB
75 行
扩展 EVM 工具生态系统。
Arbiter 是一个用于有状态以太坊智能合约模拟的框架。该框架具有基于 revm 的 ethers-rs
中间件,允许最终用户像与以太坊节点交互一样与沙盒中的 revm
实例交互。这为与以太坊虚拟机(EVM)交互提供了一个熟悉的接口,但速度更快。此外,Arbiter 还提供了模拟的封装和管理。有关使用 Arbiter 发现的漏洞列表,请参阅漏洞语料库。
概述
Arbiter 工作区有三个 crate
arbiter
:二进制 crate,通过模板仓库初始化模拟并生成所需模拟的合约绑定,公开命令行界面。arbiter-core
:lib crate,包含 Arbiter 框架的核心逻辑,包括之前讨论过的RevmMiddleware
,将模拟封装的Environment
,以及控制一组环境的Manager
。arbiter-derive
:lib crate,包含用于更简洁模拟构建的自定义 derive 宏。
Arbiter 的目的是提供一套工具来构建任意代理(由 Rust 定义、由智能合约定义或甚至其他外国函数接口),并让这些代理与您设计的类似以太坊的环境交互。所有合约字节码都直接使用闪电般的 EVM 实例 revm
(在实时 RPC 节点如 reth
中使用)运行,以便您的合约在与其部署相同的精确环境中进行测试。
动机
智能合约工程师需要测试他们的合约与各种潜在的敌对环境和合约参数。合约的静态无状态测试只能走这么远。要真正测试合约的安全性,需要将其与涵盖以太坊主网外部性的广泛动态环境进行测试。我们希望通过Arbiter实现这一点。
在去中心化金融(DeFi)中,智能合约工程师和金融工程师共同合作,分别构建和部署各种复杂的去中心化应用程序和金融策略。对于后者,金融工程师可能希望测试他们的策略,针对数千种市场状况、合约设置、冲击以及自主或随机甚至AI代理,同时确保他们的策略不会被字节码级别的漏洞利用。
使用Arbiter通过更改中间件的选择,在测试或本地网络上配置如此丰富的模拟环境也是可能的。为了获得强大且快速的模拟,最有效的方法是绕过任何网络并使用低级语言的EVM实现。此外,我们可以通过直接在revm
上工作来控制EVM世界状态。我们希望用户能够在模拟合约时有选择权,而Arbiter提供了这种选择。
模拟驱动开发和战略规划
测试驱动开发是一种流行的工程实践,即先编写测试,测试失败,然后实现逻辑以使测试最终通过。使用模拟驱动开发,可以构建“测试”,只有当激励措施真正起作用时才能通过。例如,模拟驱动测试可能是is_loan_liquidated
,并且必须为清算代理进行模拟以执行清算。这种方法显著提高了对经济系统和其他机制设计的测试,这对于主要是激励驱动的网络世界非常重要。
这同样适用于开发希望在实时以太坊网络上部署的策略。可以使用Arbiter模拟策略,并观察它是否真正起作用。这在DeFi世界中尤为重要,因为策略通常是链上和链下混合的,容易受到攻击。
安装
要安装Arbiter,您需要在您的机器上安装Rust。您可以通过以下说明安装Rust:这里。安装Rust后,您可以通过运行以下命令安装Arbiter:
cargo install arbiter
这将安装Arbiter二进制文件到您的机器上。然后,您可以通过运行arbiter --help
来查看Arbiter是否正确安装,以及查看帮助菜单。
命令行界面
Arbiter二进制文件提供了一个CLI,可以创建新的项目,类似于Foundry,Arbiter旨在与它协同工作。它还提供了分叉EVM网络状态并存储到磁盘的能力,这样您就可以在模拟中使用此分叉。
初始化
要创建新项目,您应该已经安装了Foundry。您可以在这里找到安装说明。要创建新的Arbiter项目,您可以运行:
arbiter init your-project-name
cd your-project-name
这将使用模板初始化新的Arbiter项目。您可以通过运行来重新生成绑定:
arbiter bind
此时模板是可执行的,您可以通过运行来运行它:
cargo run
可选参数
您可以通过运行arbiter init <simulation_name> --no-git
在初始化时从模板中删除.git
目录。
绑定
您可以在模板中的 contracts/
目录下加载或编写自己的智能合约,并开始编写自己的模拟。仲裁器将Rust智能合约绑定视为一等公民。合约绑定是通过Foundry的 forge
命令生成的。 arbiter bind
使用一些便利特性包装了 forge
,将所有绑定生成到 src/bindings 作为rust模块。Foundry的高级用户可以直接使用 forge
。
分叉
要分叉EVM网络的某个状态,您必须首先创建一个分叉配置文件。示例文件位于 example_fork
目录中。基本上,您需要提供数据存储位置、您想要的网络和区块号,以及您想要分叉的合约的元数据。
arbiter fork <fork_config.toml>
这将创建一个与配置文件中指定的网络对应的分叉,并将其存储在您指定的位置。然后,可以使用 Fork::from_disk()
方法将其加载到 arbiter-core
Environment
。
以这种方式进行分叉是为了确保所有模拟都不需要持续连接到RPC端点。
可选参数 您可以运行 arbiter fork <fork_config.toml> --overwrite
来覆盖已存在的分叉。
可选参数
您可以通过运行arbiter init <simulation_name> --no-git
在初始化时从模板中删除.git
目录。
文档
要查看Arbiter包的文档,请访问以下链接
您也将在crates.io上找到这些。
基准测试
在 arbiter-core
中,我们有一个小的基准测试套件,它比较了 RevmMiddleware
实现在 Environment
上的实现与 Anvil 本地测试网链实现。我们选择构建Arbiter的主要原因是为了获得对EVM环境的更多控制,并拥有一个更健壮的模拟框架,但我们还希望提高速度,这就是我们选择在 revm 上构建自己的接口,而不是使用Anvil(Anvil实际上使用 revm)。对于以下测试,Anvil被设置为为每笔交易挖掘区块,而不是设置强制性的区块时间,而 Environment
被设置为10.0的区块率(这是随意选择的,因为我们将在未来添加更多区块控制)。以下表格给出了 RevmMiddleware
接口在 revm 上对Anvil的初步基准测试。
要运行基准测试代码,您可以运行
cargo bench --package arbiter-core -F contracts
bench from 10/24/23 arbiter-core v0.6.3
操作 | RevmMiddleware | Anvil | 相对差异 |
---|---|---|---|
部署 | 238.975µs | 7712.436µs | ~32.2729x |
查找 | 565.617µs | 17880.124µs | ~31.6117x |
无状态调用 | 1402.524µs | 10397.55µs | ~7.413456x |
有状态调用 | 2043.88µs | 154553.225µs | ~75.61756x |
bench from 06/??/23ish arbiter-core v0.4.??
操作 | RevmMiddleware | Anvil | 相对差异 |
---|---|---|---|
部署 | 241.819µs | 8.215446ms | ~33.97x |
查找 | 480.319µs | 13.052063ms | ~27.17x |
无状态调用 | 4.03235ms | 10.238771ms | ~2.53x |
有状态调用 | 843.296µs | 153.102478ms | ~181.55x |
以上可以描述为
-
部署:将合约部署到EVM。我们在该方法中部署了
ArbiterToken
和ArbiterMath
,所以您可以将时间除以2来得到部署单个合约所需时间的估计。 -
查找:在本方法中查找客户端地址的
balanceOf
对应的ArbiterToken
的余额。我们在这个方法中调用了ArbiterToken
的balanceOf
函数 100 次。除以 100 得到查找单个余额所需的时间。 -
无状态调用:调用不修改状态的合约。在这个方法中我们调用了
ArbiterMath
的cdf
函数 100 次。除以 100 得到调用单个无状态函数所需的时间。 -
有状态调用:调用修改状态的合约。在这个调用中我们调用了
ArbiterToken
的mint
函数 100 次。除以 100 得到调用单个有状态函数所需的时间。
基准测试代码可以在 arbiter-core/benches/
目录中找到,这些特定时间是在 1000 次运行的平均值中实现的。上述结果是通过运行 cargo bench --package arbiter-core
实现的,这将自动以发布配置运行。在 Apple Macbook Pro M1 Max 上,使用 8 个性能核心和 2 个效率核心,以及 32GB 的 RAM 时实现了这些时间。
当然,Anvil 和 RevmMiddleware
的用例可以不同。Anvil 代表了一个更真实的具有网络和挖掘的环境,而 RevmMiddleware
是一个更简单的环境,仅包含运行有状态模拟的最基本元素。Anvil 还为每笔交易挖掘区块,而 RevmMiddleware
则不这样做。我们希望改进我们的 API,以便最终用户能够根据自己的需求与选择的 EVM 环境进行交互!
如果您在这些基准测试中发现任何问题或对改进它们有任何建议,请告诉我们!
测试
如果您做出贡献,请为新编写的任何代码编写测试,要运行测试,您可以运行
cargo test --all --all-features
贡献
查看我们的 贡献指南
依赖关系
~2MB
~42K SLoC