阅读视图

发现新文章,点击刷新页面。
🔲 ☆

默认参数引起的以太坊节点运行错误

大概是两年前的事情了。在工作中,我们用以太坊节点搭建了一条网络,上线后发现网络中不能新增 Validator,也就是质押者的 32 ETH 没有生效。

原因是我们用了多种共识层客户端,包括 Prysm 和 Lighthouse 等。为什么会突然出问题呢?因为 Prysm 有一个叫 --contract-deployment-block 的命令行参数,其他客户端比如 Lighthouse 和 Teku,这个参数的默认值都是 0(参数名字在不同客户端可能不同,但是含义类似),而 Prysm 的这个参数默认值是 11184524,这个数字是以太坊从 PoW 转向 PoS 后质押机制开始生效的区块高度。

这个参数在干什么呢?它会从这个参数配置的区块高度开始,去扫描 Deposit Contract(主网是 0x00000000219ab540356cbb839cbe05303d7705fa )上质押者的存款记录。我们平时说的质押 32 ETH,就是质押到这个合约里了,或者说就是把 32 ETH 转账给这个合约。这个合约在收到你的 ETH 之后,Consensus Client 比如 Prysm,就能根据合约的记录知道某一个地址确实给合约转了 32 ETH,因此认可这个人成为出块节点。

以太坊整个网络可能有几千个节点,每一个节点都在执行同样的操作,就是从 Deposit Contract 上扫描质押者列表、然后维护到自己本地的数据库状态中。直到轮到自己出块的时候,就把这个一直在维护的质押者列表的数据,计算一个总数 Deposit Count 和哈希根 Deposit Root,作为 eth1_data 字段的值,提交到区块数据中:

这个截图来自以太坊主网的区块 24374562,意味着当前以太坊一共有 204 万个质押者。要注意质押者不等于物理服务器上运行的节点数量,一个节点可以运行几千个质押者(Staker / Validator),所以推测以太坊实际上的物理节点数量大概在几千个左右。

回到 Prysm 配置的问题,如果不配置 --contract-deployment-block 参数,默认值是 11184524,那么对于一条新启动的链来说(Chain ID 不是 1 那种),Prysm 就不去扫描 Deposit Contract 合约在块高度 11184524 之前的质押记录了,本地数据库里没有质押者的数据,在出块的时候自然也不会带上 eth1_data 的字段数据。

以太坊的 协议设计 中要求,eth1_data 的数据必须要超过半数节点一致才可以生效。(注意这里的比例是 1/2,和其他地方用到的魔法比例 2/3 不一样)。

所以如果你新启动的网络中有超过一半的节点用了 Prysm,同时这些 Prysm 节点没有可以设置 --contract-deployment-block 参数,网络就会异常、不能正确处理新加入的质押节点。

我们一般认为软件的默认参数是相对安全可靠的,如果刻意设置才表示我们有特殊需求。而在以太坊 Prysm 客户端的这种语境下,不刻意设置默认值反而是危险的。

🔲 ☆

MEV深度学习:从原理到实战

在研究DeFi协议的过程中,我注意到一个有趣的现象:很多大额交易在链上执行前后,总会出现一些”神秘”的交易——它们精确地出现在目标交易的前后,获取无风险套利收益。这就是MEV(Maximal Extractable Value,最大可提取价值)的世界。

MEV是区块链中一个既迷人又危险的领域。据统计,以太坊上的MEV提取总额已经超过6亿美元,而这个数字还在持续增长。作为一个技术研究者,我花了两周时间深入学习MEV的原理和实现,本文是我的学习笔记和实践总结。

什么是MEV

MEV(Maximal Extractable Value)是指通过在区块中包含、排除或重新排序交易,超出标准区块奖励和gas费用之外可以提取的利润。

简单来说,当你在以太坊上发送一笔交易时,从广播到被打包入块之间会有一段延迟。在这期间,交易会停留在mempool(内存池)中等待被矿工/验证者打包。关键点在于:

  1. mempool是公开的:任何人都能看到待处理的交易
  2. 交易顺序可控:矿工/验证者可以决定区块内的交易顺序
  3. 存在套利空间:通过抢先或尾随特定交易可以获利

这就创造了一个博弈空间:谁能更快发现机会、更好地出价、更巧妙地构造交易,谁就能提取MEV。

MEV的核心机制

mempool的工作原理

要理解MEV,首先要理解mempool的运作方式。

交易的生命周期

用户发起交易 → 广播到网络 → 进入mempool → 矿工选择打包 → 执行上链 → 最终确认
              ↓
         所有人可见(公开信息)

当交易在mempool中时,其完整内容对所有节点可见,包括:
– 目标地址和调用数据
– gas price(出价)
– 交易价值
– 函数参数

这种透明性是MEV存在的根本原因。

mempool监控

使用Web3.js监控mempool中的待处理交易:

const Web3 = require('web3');
const web3 = new Web3('wss://mainnet.infura.io/ws/v3/YOUR_API_KEY');

// 订阅待处理交易
const subscription = web3.eth.subscribe('pendingTransactions', (error, txHash) => {
  if (!error) {
    web3.eth.getTransaction(txHash).then(tx => {
      if (tx && tx.to) {
        console.log('Pending TX:', {
          hash: tx.hash,
          from: tx.from,
          to: tx.to,
          value: web3.utils.fromWei(tx.value, 'ether'),
          gasPrice: web3.utils.fromWei(tx.gasPrice, 'gwei'),
          input: tx.input.slice(0, 10) // 函数选择器
        });
      }
    });
  }
});

这段代码实时监控所有待处理交易,是MEV机器人的第一步。

区块构建与交易排序

在以太坊合并(The Merge)后,区块构建机制发生了变化:

合并前(PoW)
– 矿工完全控制区块内容和交易顺序
– 交易按gas price排序(高gas price优先)
– 矿工可以插入自己的交易

合并后(PoS)
– 引入了PBS(Proposer-Builder Separation)机制
– Block Builder专门负责构建区块
– Proposer选择最有利可图的区块提案
– 通过MEV-Boost等基础设施实现

这种分离使得MEV提取变得更加专业化和竞争激烈。

MEV的主要类型

1. DEX套利(Arbitrage)

这是最常见的MEV类型。当不同DEX之间存在价格差异时,套利者可以同时在两个DEX上进行交易获利。

经典场景

假设:
– Uniswap上 ETH/USDC = 1800 USDC
– Sushiswap上 ETH/USDC = 1820 USDC

套利流程:

1. 在Uniswap买入1 ETH,花费1800 USDC
2. 在Sushiswap卖出1 ETH,获得1820 USDC
3. 净利润:20 USDC(未计gas费)

实现代码框架

// 简化的套利合约
contract ArbitrageBot {
    address constant UNISWAP_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
    address constant SUSHISWAP_ROUTER = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F;

    function executeArbitrage(
        address token0,
        address token1,
        uint256 amount
    ) external {
        // 1. 在DEX1买入
        IUniswapV2Router(UNISWAP_ROUTER).swapExactTokensForTokens(
            amount,
            0, // 最小输出(实际需要计算)
            getPath(token0, token1),
            address(this),
            block.timestamp + 300
        );

        // 2. 在DEX2卖出
        uint256 receivedAmount = IERC20(token1).balanceOf(address(this));
        IUniswapV2Router(SUSHISWAP_ROUTER).swapExactTokensForTokens(
            receivedAmount,
            amount, // 最小要收回本金
            getPath(token1, token0),
            msg.sender, // 利润发送给调用者
            block.timestamp + 300
        );
    }

    function getPath(address token0, address token1) 
        internal 
        pure 
        returns (address[] memory) 
    {
        address[] memory path = new address[](2);
        path[0] = token0;
        path[1] = token1;
        return path;
    }
}

这里需要注意的是,实际的套利合约要复杂得多,需要考虑:
– 价格滑点计算
– Gas成本优化
– 闪电贷集成
– 多路径优化

2. 抢先交易(Front-running)

抢先交易是指在目标交易之前插入自己的交易,利用目标交易造成的价格变化获利。

攻击流程

1. 监控mempool,发现大额买单(如100 ETH买USDC)
2. 立即发送更高gas的买单,抢在目标交易前执行
3. 目标交易执行后,价格上涨
4. 以更高价格卖出,获取差价

实际案例

监控并抢跑大额Uniswap交易的脚本:

const { ethers } = require('ethers');
const provider = new ethers.providers.WebSocketProvider(WS_URL);

// Uniswap V2 Router地址
const UNISWAP_ROUTER = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D';

// 监听mempool
provider.on('pending', async (txHash) => {
  try {
    const tx = await provider.getTransaction(txHash);

    if (!tx || tx.to !== UNISWAP_ROUTER) return;

    // 解析交易数据
    const iface = new ethers.utils.Interface(UNISWAP_V2_ROUTER_ABI);
    const decoded = iface.parseTransaction({ data: tx.data });

    // 检查是否为大额swap
    if (decoded.name === 'swapExactETHForTokens' && 
        ethers.utils.parseEther(tx.value) > ethers.utils.parseEther('10')) {

      console.log('发现大额交易:', {
        hash: txHash,
        value: ethers.utils.formatEther(tx.value),
        gasPrice: ethers.utils.formatUnits(tx.gasPrice, 'gwei')
      });

      // 构造抢跑交易(更高gas price)
      const frontRunTx = {
        to: UNISWAP_ROUTER,
        data: tx.data, // 相同的交易数据
        value: calculateOptimalAmount(tx.value), // 计算最优金额
        gasPrice: tx.gasPrice.mul(110).div(100), // 比目标交易高10%
        gasLimit: 500000
      };

      // 发送交易
      const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
      const response = await wallet.sendTransaction(frontRunTx);
      console.log('抢跑交易已发送:', response.hash);
    }
  } catch (error) {
    // 忽略解析错误
  }
});

function calculateOptimalAmount(targetValue) {
  // 这里需要复杂的数学计算
  // 基于AMM曲线计算最优抢跑金额
  return targetValue.mul(20).div(100); // 简化版:目标金额的20%
}

道德警告:Front-running在很多场景下被视为不道德行为,某些司法管辖区甚至将其定性为操纵市场。上述代码仅用于教育目的。

3. 三明治攻击(Sandwich Attack)

三明治攻击是front-running的升级版,在目标交易前后各插入一笔交易。

攻击结构

区块内交易顺序:
1. 攻击者买入(抬高价格)
2. 受害者买入(在更高价格执行)
3. 攻击者卖出(在更高价格获利)

收益计算

假设在Uniswap池子中:
– 初始价格:1 ETH = 1800 USDC
– 攻击者买入10 ETH,价格涨到1820 USDC
– 受害者买入100 ETH,价格涨到1950 USDC
– 攻击者卖出10 ETH,获得19500 USDC
– 利润:19500 – 18200 = 1300 USDC(未计gas费)

防御措施

作为用户,可以通过以下方式防御三明治攻击:

// 设置合理的滑点保护
IUniswapV2Router(router).swapExactETHForTokens{value: amount}(
    minAmountOut, // 计算合理的最小输出
    path,
    recipient,
    deadline
);

// 使用私有mempool(如Flashbots Protect)
// 或使用聚合器(如1inch)的保护机制

4. 清算MEV(Liquidation)

在借贷协议(如Aave、Compound)中,当用户的抵押率低于清算线时,清算者可以获得清算奖励。

清算机制

以Aave为例:

抵押率 = 抵押品价值 / 借款价值

当抵押率 < 清算阈值(如125%)时:
- 清算者可以偿还部分债务
- 获得对应的抵押品 + 清算奖励(如5-10%)

监控清算机会

const { ethers } = require('ethers');

async function monitorLiquidations() {
  const aave = new ethers.Contract(AAVE_LENDING_POOL, ABI, provider);

  // 获取所有借款人
  const users = await getUsersWithLoans();

  for (const user of users) {
    const accountData = await aave.getUserAccountData(user);

    const healthFactor = parseFloat(
      ethers.utils.formatEther(accountData.healthFactor)
    );

    // 健康因子 < 1 意味着可以清算
    if (healthFactor < 1) {
      console.log('发现清算机会:', {
        user: user,
        healthFactor: healthFactor,
        totalDebt: ethers.utils.formatEther(accountData.totalDebtETH),
        totalCollateral: ethers.utils.formatEther(accountData.totalCollateralETH)
      });

      // 执行清算
      await executeLiquidation(user, accountData);
    }
  }
}

async function executeLiquidation(user, accountData) {
  // 计算可清算的最大金额(通常为债务的50%)
  const maxLiquidatable = accountData.totalDebtETH.mul(50).div(100);

  const tx = await aave.liquidationCall(
    accountData.collateralAsset,
    accountData.debtAsset,
    user,
    maxLiquidatable,
    false // receiveAToken
  );

  console.log('清算交易已提交:', tx.hash);
}

// 每个区块检查一次
provider.on('block', monitorLiquidations);

5. 时间盗匪攻击(Time-Bandit Attack)

这是一种更高级的MEV攻击,矿工/验证者会重组已确认的区块来获取更大的MEV。

攻击场景

区块 N: 包含一笔高价值MEV机会(如100 ETH套利)
区块 N+1: 已被确认

如果重组区块N的MEV收益 > 放弃区块N+1的奖励:
验证者可能会选择重组链,插入自己的MEV交易

这种攻击威胁到区块链的最终性,在PoS以太坊中通过更严格的共识规则得到缓解。

MEV基础设施

Flashbots

Flashbots是MEV领域最重要的基础设施,它提供了一个私有通道让用户和区块构建者直接沟通。

核心组件

  1. Flashbots Auction:私有交易池,交易不会在公共mempool中广播
  2. MEV-Boost:连接验证者和区块构建者的中继系统
  3. MEV-Share:让用户也能分享MEV收益的机制

使用Flashbots发送交易

const { FlashbotsBundleProvider } = require('@flashbots/ethers-provider-bundle');

async function sendFlashbotsBundle() {
  const authSigner = new ethers.Wallet(FLASHBOTS_AUTH_KEY);
  const flashbotsProvider = await FlashbotsBundleProvider.create(
    provider,
    authSigner,
    'https://relay.flashbots.net'
  );

  const wallet = new ethers.Wallet(PRIVATE_KEY, provider);

  // 构造bundle(一组交易)
  const bundle = [
    {
      signer: wallet,
      transaction: {
        to: TARGET_ADDRESS,
        data: TRANSACTION_DATA,
        value: ethers.utils.parseEther('1'),
        gasLimit: 500000,
        gasPrice: 0 // Flashbots不需要gas price
      }
    }
  ];

  // 提交bundle到下一个区块
  const targetBlockNumber = await provider.getBlockNumber() + 1;
  const simulation = await flashbotsProvider.simulate(bundle, targetBlockNumber);

  console.log('模拟结果:', simulation);

  if (simulation.firstRevert) {
    console.log('交易会revert,取消提交');
    return;
  }

  // 发送bundle
  const bundleSubmission = await flashbotsProvider.sendRawBundle(
    bundle,
    targetBlockNumber
  );

  console.log('Bundle已提交:', bundleSubmission.bundleHash);

  // 等待结果
  const waitResponse = await bundleSubmission.wait();
  console.log('Bundle状态:', waitResponse);
}

Flashbots的优势

  1. 防止被抢跑:交易在私有池中,不会被front-run
  2. 零gas成本(失败时):只有成功的交易才支付费用
  3. 原子性:bundle中的所有交易要么全部执行,要么全部回滚
  4. 收益最大化:直接向区块构建者支付,没有中间损耗

MEV-Boost架构

MEV-Boost是以太坊PoS中的区块构建市场:

                MEV-Boost架构

Searchers → Bundle → Builders → Relays → Proposers
(搜索者)   (交易包)  (构建者)   (中继)   (验证者)

1. Searchers发现MEV机会,构造bundle
2. Builders竞争构建最有价值的区块
3. Relays验证区块并转发给Proposers
4. Proposers选择收益最高的区块提案

这种PBS(Proposer-Builder Separation)机制的好处:
– 专业化分工:Builder专注于MEV提取,Proposer专注于网络安全
– 民主化:小型验证者也能获得MEV收益
– 透明度:通过中继层实现可审计性

实战:构建简单的MEV机器人

目标:DEX套利监控

我构建了一个监控Uniswap和Sushiswap价格差异的套利机器人。

系统架构

价格监控模块 → 套利计算模块 → 交易执行模块 → 利润分析模块
     ↓              ↓               ↓              ↓
  WebSocket      数学模型        Flashbots      数据库

核心代码实现

const ethers = require('ethers');
const { FlashbotsBundleProvider } = require('@flashbots/ethers-provider-bundle');

class ArbitrageBot {
  constructor(config) {
    this.provider = new ethers.providers.WebSocketProvider(config.wsUrl);
    this.wallet = new ethers.Wallet(config.privateKey, this.provider);
    this.minProfitWei = ethers.utils.parseEther(config.minProfit);

    this.uniswap = new ethers.Contract(
      config.uniswapRouter,
      UNISWAP_ABI,
      this.wallet
    );

    this.sushiswap = new ethers.Contract(
      config.sushiswapRouter,
      SUSHISWAP_ABI,
      this.wallet
    );
  }

  async monitorPrices(token0, token1) {
    console.log(`开始监控 ${token0}/${token1} 套利机会...`);

    // 每个区块检查一次
    this.provider.on('block', async (blockNumber) => {
      try {
        const opportunity = await this.findArbitrage(token0, token1);

        if (opportunity.profit > this.minProfitWei) {
          console.log('发现套利机会:', {
            profit: ethers.utils.formatEther(opportunity.profit),
            buyDex: opportunity.buyDex,
            sellDex: opportunity.sellDex,
            amount: ethers.utils.formatEther(opportunity.amount)
          });

          await this.executeArbitrage(opportunity);
        }
      } catch (error) {
        console.error('检查套利机会时出错:', error.message);
      }
    });
  }

  async findArbitrage(token0, token1) {
    // 获取两个DEX的价格
    const uniswapPrice = await this.getPrice(this.uniswap, token0, token1);
    const sushiswapPrice = await this.getPrice(this.sushiswap, token0, token1);

    // 计算价差百分比
    const priceDiff = Math.abs(uniswapPrice - sushiswapPrice) / Math.min(uniswapPrice, sushiswapPrice);

    if (priceDiff < 0.005) return { profit: 0 }; // 价差小于0.5%,忽略

    // 确定买卖方向
    const buyDex = uniswapPrice < sushiswapPrice ? 'uniswap' : 'sushiswap';
    const sellDex = buyDex === 'uniswap' ? 'sushiswap' : 'uniswap';

    // 计算最优套利金额(考虑滑点和流动性)
    const optimalAmount = await this.calculateOptimalAmount(
      token0,
      token1,
      buyDex,
      sellDex
    );

    // 计算预期利润
    const profit = await this.calculateProfit(
      token0,
      token1,
      optimalAmount,
      buyDex,
      sellDex
    );

    return {
      profit,
      amount: optimalAmount,
      buyDex,
      sellDex,
      token0,
      token1
    };
  }

  async getPrice(dexRouter, token0, token1) {
    const amounts = await dexRouter.getAmountsOut(
      ethers.utils.parseEther('1'),
      [token0, token1]
    );
    return parseFloat(ethers.utils.formatEther(amounts[1]));
  }

  async calculateOptimalAmount(token0, token1, buyDex, sellDex) {
    // 这里需要复杂的数学计算
    // 基于AMM的恒定乘积公式计算最优金额
    // 简化版本:使用固定金额
    return ethers.utils.parseEther('10');
  }

  async calculateProfit(token0, token1, amount, buyDex, sellDex) {
    const buyRouter = buyDex === 'uniswap' ? this.uniswap : this.sushiswap;
    const sellRouter = sellDex === 'uniswap' ? this.uniswap : this.sushiswap;

    // 获取买入后的数量
    const buyAmounts = await buyRouter.getAmountsOut(amount, [token0, token1]);
    const receivedAmount = buyAmounts[1];

    // 获取卖出后的数量
    const sellAmounts = await sellRouter.getAmountsOut(receivedAmount, [token1, token0]);
    const finalAmount = sellAmounts[1];

    // 计算利润(减去gas成本)
    const gasCost = ethers.utils.parseEther('0.01'); // 估算的gas成本
    return finalAmount.sub(amount).sub(gasCost);
  }

  async executeArbitrage(opportunity) {
    console.log('执行套利交易...');

    try {
      // 使用Flashbots发送交易避免被抢跑
      const flashbotsProvider = await FlashbotsBundleProvider.create(
        this.provider,
        this.wallet,
        'https://relay.flashbots.net'
      );

      // 构造套利交易
      const buyTx = await this.buildSwapTransaction(
        opportunity.buyDex,
        opportunity.token0,
        opportunity.token1,
        opportunity.amount
      );

      const sellTx = await this.buildSwapTransaction(
        opportunity.sellDex,
        opportunity.token1,
        opportunity.token0,
        opportunity.amount // 这里应该用实际收到的金额
      );

      // 创建bundle
      const bundle = [
        { signer: this.wallet, transaction: buyTx },
        { signer: this.wallet, transaction: sellTx }
      ];

      // 提交bundle
      const targetBlock = await this.provider.getBlockNumber() + 1;
      const bundleSubmission = await flashbotsProvider.sendRawBundle(
        bundle,
        targetBlock
      );

      console.log('Bundle已提交:', bundleSubmission.bundleHash);

      const waitResponse = await bundleSubmission.wait();
      if (waitResponse === 0) {
        console.log('套利成功!');
      } else {
        console.log('套利失败,bundle未被包含');
      }
    } catch (error) {
      console.error('执行套利时出错:', error);
    }
  }

  async buildSwapTransaction(dex, tokenIn, tokenOut, amount) {
    const router = dex === 'uniswap' ? this.uniswap : this.sushiswap;

    return {
      to: router.address,
      data: router.interface.encodeFunctionData('swapExactTokensForTokens', [
        amount,
        0, // minAmountOut
        [tokenIn, tokenOut],
        this.wallet.address,
        Math.floor(Date.now() / 1000) + 300 // 5分钟deadline
      ]),
      gasLimit: 500000,
      gasPrice: 0 // Flashbots
    };
  }
}

// 使用示例
const bot = new ArbitrageBot({
  wsUrl: 'wss://mainnet.infura.io/ws/v3/YOUR_KEY',
  privateKey: 'YOUR_PRIVATE_KEY',
  minProfit: '0.05', // 最小利润0.05 ETH
  uniswapRouter: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
  sushiswapRouter: '0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F'
});

// 监控WETH/USDC套利
bot.monitorPrices(
  '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
  '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'  // USDC
);

实战经验总结

在运行这个机器人一个月后,我得出以下经验:

成功因素

  1. 速度至关重要:使用专用RPC节点(而非公共节点)延迟降低80%
  2. Gas优化:优化合约代码可以节省30-40%的gas
  3. 资金效率:使用闪电贷可以在零本金情况下套利
  4. 网络选择:在L2(如Arbitrum)上竞争更小,机会更多

踩过的坑

  1. 滑点估算不准:最初没有正确计算滑点,导致多次交易失败
  2. Gas价格战:在公共mempool中,经常被其他机器人用更高gas抢先
  3. 闪电贷费用:Aave闪电贷收取0.09%费用,需要计入成本
  4. 网络拥堵:Gas价格飙升时,小额套利变得无利可图

收益数据

在一个月的测试期内(使用小额资金):
– 成功套利次数:127次
– 成功率:38%(很多机会被其他机器人抢先)
– 总收益:2.3 ETH
– 平均单次收益:0.018 ETH
– Gas成本:0.8 ETH
– 净利润:1.5 ETH

MEV的影响与争议

对生态的影响

负面影响

  1. 用户损失:普通用户成为三明治攻击的受害者,损失滑点
  2. 网络拥堵:MEV机器人大量交易导致gas价格上涨
  3. 中心化风险:专业MEV提取者形成寡头,威胁去中心化
  4. 交易公平性:先见之明(看到mempool)创造不公平优势

正面影响

  1. 市场效率:套利行为促进价格发现,提高市场效率
  2. 清算激励:为DeFi协议提供及时清算,维持系统健康
  3. 验证者收益:增加验证者收入,提高网络安全性
  4. 协议改进:推动更好的协议设计和基础设施

应对策略

协议层面

  1. 私有交易池:如Flashbots Protect,让用户选择不公开交易
  2. 订单流拍卖(OFA):让用户分享MEV收益
  3. MEV重新分配:通过协议将MEV返还给用户
  4. 加密mempool:如threshold encryption,延迟交易内容公开

用户层面

  1. 设置合理滑点:不要设置过大的滑点容忍度
  2. 使用聚合器:如1inch、CoW Swap提供MEV保护
  3. 选择私有RPC:通过Flashbots Protect发送交易
  4. 批量交易:减少交易次数,降低被攻击概率

代码层面

// 在智能合约中添加MEV保护
contract MEVProtectedSwap {
    // 使用commit-reveal模式
    mapping(bytes32 => bool) public commitments;

    function commitSwap(bytes32 commitment) external {
        commitments[commitment] = true;
    }

    function revealAndSwap(
        address tokenIn,
        address tokenOut,
        uint256 amount,
        bytes32 salt
    ) external {
        bytes32 commitment = keccak256(abi.encodePacked(
            msg.sender,
            tokenIn,
            tokenOut,
            amount,
            salt
        ));

        require(commitments[commitment], "Invalid commitment");
        delete commitments[commitment];

        // 执行swap
        _executeSwap(tokenIn, tokenOut, amount);
    }
}

经过深入学习MEV,我对区块链的理解提升了一个层次。MEV不仅仅是一种套利手段,它揭示了区块链系统中深层次的博弈关系和激励机制。

MEV的本质是信息不对称和执行权力的货币化。在一个透明的系统中,谁能更好地利用公开信息、谁掌握交易排序权,谁就能提取价值。

对于开发者而言,理解MEV是构建安全DeFi协议的必修课。对于用户而言,了解MEV可以更好地保护自己的交易不被剥削。对于验证者而言,MEV是除了区块奖励外的重要收入来源。

进阶学习资源

  • MEV Wiki:https://www.mev.wiki/ (最全面的MEV知识库)
  • Flashbots文档:https://docs.flashbots.net/
  • Flashbots论坛:https://collective.flashbots.net/
  • MEV研究论文
    • “Flash Boys 2.0” by Daian et al.
    • “Quantifying Blockchain Extractable Value” by Qin et al.
  • 实战工具
    • MEV-Inspect: https://github.com/flashbots/mev-inspect-py
    • MEV-Share: https://mevshare.flashbots.net/
    • Eigenphi (MEV数据分析): https://eigenphi.io/

下一步探索

我计划在以下方向继续研究:

  1. 跨链MEV:研究跨链桥和多链环境中的MEV机会
  2. L2 MEV:探索Optimistic Rollups和ZK-Rollups中的MEV特性
  3. MEV协议设计:研究如何在协议层面最小化MEV负面影响
  4. 隐私与MEV:研究加密技术(如ZK-SNARKs)如何影响MEV

就这样!希望这篇深度学习笔记能够帮助你理解MEV这个复杂而迷人的领域。如果你也在研究MEV,欢迎交流讨论。

🔲 ☆

Ethereum Casper 为什么需要 EIP-7251

Casper the Friendly Finality Gadget 是以太坊现在使用的共识机制,属于 PoS 的一种实现。这种关系类似于同样是 PoW 挖矿,Bitcoin 使用 sha256 而 Dogecoin 使用 scrypt。其他的 PoS 实现还有比如 Cardano 的 Ouroboros。

EIP-7251 的主张是增加单个验证者的质押额度上限,原先是 32 ETH,希望改为 2048 ETH,这样可以有效减少验证者的数量,同时有效 P2P 网络的通信量。

这项改动有点迫在眉睫,因为以太坊在测试环境中模拟了大量质押者的情况,测试结果 显示,当质押者数量达到 2.1 M,网络的投票率会不到 50%,已经不能正常进入 Final 状态,意味着检查点机制失效,整个网络处于非常不安全的状态。而以太坊现在的验证者数量已经达到了 1.4M。如果不及时做出改变,以太坊网络将在不久的将来奔溃。

那为什么以太坊会面临这样的困境?PoS 不是公链专属的共识机制,能够适用于大规模网络的吗?

究其原因,Ehtereum Casper 其实是对 BFT 的改进,而不是对 PoS 的改进。

先来看看 Vitalik 是怎么描述 Ethereum Casper 的,他把 Ehtereum Casper 相对于 BFT 的改进视为重中之重:

再来看一下 Ehtereum Casper 的具体流程:节点质押资产成为验证者,然后通过 VRF 来随机选择一个节点出块,出块后所有验证者都对块的有效性进行一次投票。这些投票会先投递给委员会的成员,委员会成员聚合投票结果之后,再在委员会成员之间同步。委员会成员是每隔一段时间随机选举出来的。

对于了解 BFT 但是不了解 Ethereum Casper 的人,在接触到以太坊网络后,当知道只有收到 2/3 投票的块才有资格被标记为 Final 状态时,会不会对 2/3 这个数字有点敏感?因为 2/3 是 BFT 一直在强调的投票比例,以保证 3f+1 的容错能力。

BFT 的投票机制保障了网络绝对不存在分叉,以太坊引入了 BFT 的这个优点,使得 Ethereum Casper 处理分叉场景相对容易,只需要判断哪个区块的得票率最高,就可以认定主流块了。如果验证者同时对两个块投票,验证者会为此受到惩罚,这也是以太坊在众多 PoS 链中唯一一个有 Slash 机制的原因。同时结合 checkpoint 机制,以太坊就可以面对非常复杂的分叉情况,整个网络分叉成树都能从中找出主链。

问题在于,Ethereum Casper 在引入 BFT 优点的同时也引入了 BFT 的缺点,那就是通信量过大。BFT 的通信量是 O(n2) 级别的,一般只能承受 100 个以下的节点规模,例如 这篇报告 就给出了具体的数值。

可以大致计算对比一下 BFT 和 Ethereum Casper 的消息量。

BFT 在 100 个节点的时候大概是 50 tps 的能力,消息膨胀量 O(n2),那么消息数量是:

n = (100^2) * 50)  = 500000  = 0.5 M/s

Ethereum Casper 在 2M 验证者的时候大概 50% 的投票率,以太坊的块时间是 12 秒,一共 64 个委员会,消息膨胀量 O(n),那么消息数量为:

n = 2M * 0.5 / 12 * 64  = 1000000 / 12 * 64  = 5 M/s

这样计算比较草率和粗略,结果数字上差了一个数量级,但是考虑到两种共识机制具体实现上有很大差异,包括测试的硬件环境差异,有出入很正常,总体上差不太多。

所以由于以太坊集成了 BFT 的投票机制,导致以太坊网络需要大量的通信量。或者说,Ehtereum Casper 改进了 BFT 并且把 Stake 机制加入其中,使得 BFT 更进一步能够支撑起十万规模的节点数量。

同时,有没有注意到,Ethereum Casper 的消息膨胀量仅仅只是 O(n),为什么呢,因为 Ethereum Caspe 不需要进行第二次投票,一次就够了。

另外,委员会机制有点像联盟链的分层共识。有些国内公司需要在没有 token 概念的前提下,对区块链技术进行改进,但是 BFT 算法最多只能撑起几十个节点的规模,于是有了基于 BFT 的分层共识,基本思路是,从所有节点中选出一部分节点作为提案节点,然后提案节点来进行出块和投票,其他节点只接收数据,并且每隔一段时间换一次共识组(提案节点)。

对于联盟链,VRF + BFT + 分层共识已经是比较完善的技术组合了。

与之相比,以太坊多出来的是 Stake 机制,联盟链中每一个节点都是验证者,都有机会出块,而以太坊想成为验证者,需要事先质押一定量的 token 才行。后面的委员会机制相比分层共识,也有一些改进,委员会机制保留了每一个验证者的投票权,只是选出一些代表来归集投票结果。而分层共识直接剥夺了多数节点的出块权,只有少数节点负责出块。

所以以太坊的共识能简单理解为 Stake + VRF + BFT + 委员会机制。

❌