如何使用 Artemis MEV 框架

  • mteam88
  • 发布于 2023-08-16 13:12
  • 阅读 19

本文介绍了 Paradigm 出品的 Artemis MEV 框架,该框架使用 Rust 语言编写,旨在帮助 MEV 搜索者更轻松地编写 MEV 机器人。文章详细说明了 Artemis 的架构,包括 Collectors、Strategies 和 Executors 三个主要组件,并提供了使用 Artemis 构建 MEV 机器人的步骤和建议。

发布于:2023 年 8 月 15 日 | 于晚上 11:57

ParadigmArtemis MEV 框架对于希望使用 Rust 编写 MEV 机器人的 MEV 搜索者来说是一个有用的工具。

本指南将从高层次向你介绍如何使用 Artemis 框架。它将为你提供开始使用 Rust 编写自己的 MEV 机器人所需的一切。

为什么要编写 MEV 机器人?

绝大多数人没有成为有效搜索者的技能或智力。我编写 MEV 机器人是为了学习并与搜索者社区建立联系。

编写 MEV 机器人是一次很棒的学习体验,你将学习真实的、高风险、高回报的软件工程技能。你将学习如何优化程序,并且你将学习如何编写与 Ethereum 区块链交互的软件。我强烈建议任何程序员都尝试一下,但要避免任何盈利的期望。

为什么选择 Artemis?

在本节中,我将解释为什么你应该使用 Artemis 来编写你的下一个 MEV 机器人。

Rust

Artemis 构建在 Rust 编程语言之上。Rust 是一种快速、安全且并发的编程语言。这些品质使其成为编写 MEV 机器人的绝佳选择。Rust 社区也非常乐于助人。

Rust 对 Ethereum 的支持非常出色,以下是一些使用 Rust 进行 Ethereum 相关开发的项目:

社区支持

Artemis dev telegram 频道 活跃且乐于助人。Artemis 的 issue 跟踪器 也很活跃。

有效性

自 Artemis 发布以来,MEV 活动显着增加,这表明它非常有效。  Artemis 发布后 REV 迅速增加

权衡

Artemis 并不完美。Artemis 为了开发者体验而牺牲了速度和效率。

实际上,这意味着短尾 MEV 机器人(需要毫秒级优化的机器人)不应使用 Artemis。

Artemis 先决条件

在使用 Artemis 和阅读本指南之前,你应该对以下内容有中级到高级的了解:

  • Rust
  • Ethereum
  • MEV

我写的其他关于 MEV 入门Ethereum 的文章

Artemis 入门

注意:你可以在我的 github 上找到 Artemis 入门模板

使用 Artemis 的第一步是安装 Rust。你可以在 此处 找到有关如何安装 Rust 的说明。

接下来,创建一个新文件夹并在该文件夹中打开一个终端。运行以下命令以创建一个新的 Rust 项目:

cargo new my_project

接下来,将以下内容添加到 Cargo.toml 文件中的 dependencies 部分:

artemis-core = { git = "https://github.com/paradigmxyz/artemis" }

这会将 Artemis 核心库添加到你的项目中。Artemis 核心库包含你需要使用 Artemis 作为框架的所有代码。

构建我们的 MEV 机器人

在我们开始编写 MEV 机器人之前,我们需要了解 Artemis 项目的结构。

来自 Artemis 主页

Artemis 的核心架构是一个事件处理管道。该库由三个主要组件组成:

收集器:收集器接收外部事件(例如待处理的交易、新区块、市场订单等),并将它们转换为内部事件表示形式。

策略:策略包含每个 MEV 机会所需的核心逻辑。它们将事件作为输入,并计算是否有任何机会可用(例如,策略可能会监听市场订单流,以查看是否存在任何跨交易所套利)。策略产生动作。

执行器:执行器处理动作,并负责在不同领域执行它们(例如,提交交易、发布链下订单等)。

strategy.rs 文件

这将是我们代码的主要部分。一个空的 strategy.rs 文件如下所示:

use super::types::{Action, Config, Event};
use anyhow::Result;
use artemis_core::types::Strategy;
use async_trait::async_trait;
use ethers::providers::Middleware;
use std::sync::Arc;
pub struct ExampleStrat<M> {
    client: Arc<M>,
}
impl<M: Middleware + 'static> ExampleStrat<M> {
    pub fn new(client: Arc<M>, config: Config) -> Self {
        Self { client }
    }
}
#[async_trait]
impl<M: Middleware + 'static> Strategy<Event, Action> for ExampleStrat<M> {
    async fn sync_state(&mut self) -> Result<()> {
        Ok(())
    }
    async fn process_event(&mut self, event: Event) -> Option<Action> {
        match event {}
    }
}
impl<M: Middleware + 'static> ExampleStrat<M> {}

types.rs 文件

此文件将包含我们将在 MEV 机器人中使用的类型。一个空的 types.rs 文件如下所示:

#[derive(Debug, Clone)]
pub enum Event {}
#[derive(Debug, Clone)]
pub enum Action {}
#[derive(Debug, Clone)]
pub struct Config {}

构建自定义收集器和执行器

Artemis 附带一组默认收集器:

  • BlockCollector - 从区块链收集新区块
  • LogCollector - 从区块链收集所有新日志
  • MempoolCollector - 从内存池收集待处理的交易
  • MevShareCollector - 收集 MEV-Share SSE 事件
  • OpenseaOrderCollector - 收集 OpenSea 上的新订单

和执行器:

  • FlashbotsExecutor - 将 bundles 发送到 Flashbots 中继
  • MempoolExecutor - 将交易发送到内存池
  • MevshareExecutor - 将 bundles 发送到 MEV-Share 撮合器

但我们也可以编写自己的自定义收集器和执行器。我建议为每个收集器/执行器创建一个单独的文件。

例如,这是我编写的一个将通知发送到 Telegram 频道的执行器(为了简洁而剪辑):

// Telegram Executor - telegram_executor.rs

// 导入
// --snip--

/// 一个将通知发送到 telegram 群组的执行器。
pub struct TGExecutor {
    bot: Arc<Bot>,
}

#[derive(Debug, Clone)]
pub struct Notification {
// --snip--
}

impl TGExecutor {
    pub async fn new(tg_token: String) -> Self {
        let bot = Bot::new(tg_token);
        Self { bot: Arc::new(bot) }
    }
}

#[async_trait]
impl Executor<Notification> for TGExecutor {
    /// 向 telegram 发送通知。
    async fn execute(&self, action: Notification) -> Result<()> {
        let text: String = action.into();
        info!("发送通知: {:?}", text);
        let message = self
            .bot
            .send_message("@<SNIPPED>".to_string(), text);
        let res = message.parse_mode(ParseMode::MarkdownV2).send().await;
        if let Err(e) = res {
            error!("发送通知失败: {:?}", e);
        }
        Ok(())
    }
}

impl From<Notification> for String {
    fn from(notification: Notification) -> Self {
        // --snip--
    }
}

如果你使用的收集器/执行器与智能合约交互,那么使用 ethers-rs bindings 是一个好主意。

将它们联系在一起

一旦我们有了收集器、执行器和策略,我们需要将它们协调在一起。我们在 main.rs 文件中执行此操作。

main.rs 文件

每个 Artemis 项目都有一个 main.rs 文件。此文件将包含负责初始化我们的 MEV 机器人并运行它的代码。你可以在 此处此处 找到示例。

这是 Artemis 文档中提供的 OpenSea Sudo Arb 策略示例中的 main.rs 文件的一部分:

    // 设置引擎。
    let mut engine: Engine<Event, Action> = Engine::default();

    // 设置区块收集器。
    let block_collector = Box::new(BlockCollector::new(provider.clone()));
    let block_collector = CollectorMap::new(block_collector, Event::NewBlock);
    engine.add_collector(Box::new(block_collector));

    // 设置 opensea 收集器。
    let opensea_collector = Box::new(OpenseaOrderCollector::new(args.opensea_api_key));
    let opensea_collector =
        CollectorMap::new(opensea_collector, |e| Event::OpenseaOrder(Box::new(e)));
    engine.add_collector(Box::new(opensea_collector));

    // 设置 opensea sudo arb 策略。
    let config = Config {
        arb_contract_address: H160::from_str(&args.arb_contract_address)?,
        bid_percentage: args.bid_percentage,
    };
    let strategy = OpenseaSudoArb::new(Arc::new(provider.clone()), opensea_client, config);
    engine.add_strategy(Box::new(strategy));

    // 设置 flashbots 执行器。
    let executor = Box::new(MempoolExecutor::new(provider.clone()));
    let executor = ExecutorMap::new(executor, |action| match action {
        Action::SubmitTx(tx) => Some(tx),
    });
    engine.add_executor(Box::new(executor));

    // 启动引擎。
    if let Ok(mut set) = engine.run().await {
        while let Some(res) = set.join_next().await {
            info!("res: {:?}", res);
        }
    }

在此示例中,我们可以看到 main.rs 文件负责:

  • 初始化引擎
  • 初始化收集器/策略/执行器
  • 将收集器/策略/执行器添加到引擎
  • 运行引擎

项目布局

现在我们已经看到了运行机器人所需的所有文件。我们的项目结构应如下所示:

project_name/
├── Cargo.lock // 一个锁文件,由 cargo 生成
├── Cargo.toml // 我们项目的清单,包括依赖项
├── main.rs // 我们机器人的入口点
└── src/
    ├── constants.rs // 我们可能需要的任何常量
    ├── custom_collector.rs // 我们的自定义收集器
    ├── custom_executor.rs // 我们的自定义执行器
    ├── lib.rs // 重新导出我们的模块
    ├── strategy.rs // 我们的自定义策略
    └── types.rs // 我们的自定义类型,由 Artemis 使用

机器人开发

现在我们已经设置好了项目,我们可以开始编写我们的机器人了。

研究

每个 MEV 机器人都利用特定的 MEV 机会。在编写机器人之前,我们需要找到一个可以利用的 MEV 机会。我还有其他关于此主题的文章。

一旦你想到了一个机会,你需要对其进行研究。你需要彻底了解这个机会。你需要了解风险、回报和机会的机制。

起草策略

一旦你理解了一个机会,在纸上写下你的机器人将采取的所有步骤,将它们分解成越来越小的片段。例如,如果编写一个在小型协议 XYZ 上执行清算的机器人,你的图表可能如下所示:

- 每隔一个区块从 XYZ 检索所有活跃的仓位
  - 生成一个多调合约调用,以从 XYZ 合约检索所有活跃的仓位
  - 在本地使用注入的合约模拟调用
  - 将结果存储在自定义数据结构中
- 分析所有活跃的仓位
  - 检索/计算每个仓位的清算指标
  - 检查是否可以清算该仓位
    - 如果可以清算该仓位,则生成一个交易来清算该仓位
    - 将交易发送到 Flashbots 中继,并提供动态贿赂

此外,记录你需要的任何收集器或执行器可能会有所帮助:

- BlockCollector
- XYZPositionCollector
- FlashbotsExecutor

编程

一旦你起草了一个策略,你就可以开始编写你的机器人了。设置你的机器人会根据你利用的机会而有所不同,但这里有一些提示:

  • 慢慢来,你不想犯任何代价高昂的错误
  • 经常提交,我为我的机器人使用一个私有的 GitHub 仓库
  • 从简单的事情开始,比如收集器和执行器
  • 玩得开心,不要害怕学习比你必须学习的更多的东西

我coding的时候会听 Spotify 上的 Chill Instrumental Beats,它可以帮助我集中注意力。

部署和监控

一旦你的机器人编写和测试完毕,你就可以将其部署在服务器上。我没有任何具体的建议,但一些 MEV 机器人运行在 AWS、Google Cloud、Azure、Hetzner 和 Digital Ocean 上。

监控机器人的性能非常重要。你应该监控以下内容:

  • 你的机器人发送的交易数量
  • 你的机器人花费在 gas 上的 ETH 数量
  • 你的机器人赚取的 ETH 数量
  • 你的机器人赢得目标 opp 的频率

你可以设置一个监控系统,或者一开始只使用 etherscan

结论

我希望本指南对你有所帮助。如果你有任何问题,请随时通过 DiscordTelegram 与我联系。

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

0 条评论

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