newsence
雙模式重鑄:一種在保留代幣可組合性的同時緩解 EIP-7503 生日攻擊的方案

雙模式重鑄:一種在保留代幣可組合性的同時緩解 EIP-7503 生日攻擊的方案

ethresear.ch·4 天前

本文為 ZWToken 提出了一種雙模式重鑄機制,透過引入匿名上限以及針對大額轉帳的揭露模式,來緩解 EIP-7503 中 160 位元生日攻擊的風險,並同時確保代幣在 DeFi 中的可組合性。

1. 問題陳述

1.1 背景

EIP-7503 (零知識蟲洞) 提出了一種圍繞燃燒地址(burn addresses)構建的鏈上隱私設計。ERC-8065 (零知識代幣包裝器) 定義了一個包裝器,為現有代幣添加 EIP-7503 風格的隱私功能。ZWToken 是 ERC-8065 的完整實現,支持 ERC-20、原生 ETH、ERC-721 和 ERC-1155。

作為 ERC-8065 的實現,ZWToken 繼承了 EIP-7503 中提出但未解決的核心安全問題——160 位元生日攻擊。本文檔說明了該問題以及 ZWToken 的緩解方案。

1.2 燃燒地址隱私流程

EIP-7503 的核心流程為:

  • 用戶從一個秘密(secret)推導出一個燃燒地址(隱私地址)

  • 代幣被發送到該地址(存入承諾)

  • 通過證明其知曉秘密的 ZK 證明,用戶在另一個地址**重新鑄造(remint)**等量的代幣

此流程中的隱私依賴於:沒有人能將燃燒地址與接收地址關聯起來

1.3 攻擊向量

以太坊地址為 160 位元。燃燒地址的推導方式如下:

addrScalar = Poseidon(8065, tokenId, secret) // ~254 位元
addr20 = addrScalar mod 2^160 // 截斷至 160 位元

生日攻擊可以在 2^80 次操作中找到碰撞。攻擊者並行搜索兩個空間;根據生日悖論,約 2^80 次嘗試足以找到一對匹配項:

向量 1:重複鑄造(兩個秘密碰撞到同一個地址)

Poseidon(8065, 0, secret_A) mod 2^160 == Poseidon(8065, 0, secret_B) mod 2^160

攻擊者使用 secret_A 和 secret_B 產生不同的無效符(nullifiers),並針對同一個承諾進行兩次重新鑄造。

向量 2:CREATE2 碰撞

Poseidon(8065, 0, secret) mod 2^160 == CREATE2(deployer, salt, codehash)

攻擊者利用 CREATE2 控制燃燒地址:他們可以直接提取代幣,同時也能通過 ZK 證明重新鑄造。

向量 3:EOA 私鑰碰撞

Poseidon(8065, 0, secret) mod 2^160 == keccak256(publicKey)[12:32]

攻擊者同時搜索秘密和 ECDSA 金鑰;一旦發生碰撞,他們便持有該燃燒地址的私鑰,並可以簽名轉出資金。

1.4 嚴重性

指標
數值

攻擊複雜度
2^80 次雜湊操作

128 位元安全性
2^128 次操作

差距
未達到 128 位元安全性

粗略成本估算
數百億美元的硬體成本(目前)

影響
協議通膨;資金池可能被掏空

雖然目前在經濟上不可行,但風險隨著硬體和 ASIC 優化而增加。

2. 先前技術

2.1 EIP-7503 工作量證明 (PoW)

在 ZK 電路中加入 PoW 限制:

Poseidon(MAGIC_POW, secret) mod 2^POW_BITS == 0

秘密必須滿足 PoW 條件,從而提高尋找有效秘密的成本。

優點

  • 對面向用戶的流程無改動

  • 自然地融入 ZK 電路

缺點

  • 僅改善了常數因子,而非漸近複雜度——攻擊者只需支付 2^POW_BITS 的倍數成本

  • 證明生成時間顯著增加(用戶在客戶端運行 PoW)

  • 行動端體驗較差

  • POW_BITS 難以調整:太低無效,太高則用戶無法接受

2.2 存款上限

限制每次存款/轉帳/重新鑄造的最大金額。

優點

  • 易於實現

  • 將每次攻擊的利潤限制在 2^80 生日攻擊的成本之下

缺點

  • 破壞了代幣的兼容性和可組合性——存款、轉帳等不能超過上限,因此 ZWToken(例如具備隱私功能的包裝 ERC-20)無法像標準 ERC-20 一樣與 DeFi(Uniswap、Aave 等)交互

  • 限制了合法的巨額轉帳

3. ZWToken 解決方案:雙模式重新鑄造

3.1 核心思路

設置一個低於 2^80 生日攻擊經濟成本的匿名上限(anonymousCap):

  • 金額 ≤ anonymousCap:完全匿名模式;行為與之前一致

  • 金額 > anonymousCap:揭露模式;用戶必須公佈燃燒地址;合約從該地址燃燒代幣後再進行鑄造

在最壞的情況下,經過約 2^80 的工作量後,攻擊者最多只能竊取 anonymousCap 的金額。如果 anonymousCap 設置低於 2^80 攻擊的估計成本(目前為數百億美元),則不存在理性的經濟動機。大額轉帳被迫通過「從地址燃燒」的路徑,因此通過此向量產生的通膨是不可能的

與全局存款上限不同,此限制僅適用於重新鑄造標準的 ERC-20 存款、轉帳和提款不受限制,保留了完整的兼容性和 DeFi 可組合性。UI 會將發往燃燒地址的轉帳限制在 anonymousCap 以內;普通地址之間的轉帳則無限制。

3.2 電路設計

增加一個公開輸入 revealedAddr 和一個二次約束:

signal input revealedAddr; // 0 = 匿名, addr20 = 揭露

// 如果 revealedAddr != 0,則它必須等於 addr20
revealedAddr * (revealedAddr - addr20) === 0;

  • revealedAddr = 0:匿名模式;約束自然成立

  • revealedAddr = addr20:揭露模式;證明 revealedAddr 與電路內的 addr20 匹配

  • revealedAddr = 其他任何值:約束失敗;無法生成證明

成本:增加一個額外約束(13084 → 13085);對證明時間的影響微乎其微。

3.3 合約設計

// BaseZWToken.sol
uint256 public immutable anonymousCap; // 0 = 無上限

function _requireRevealIfNeeded(uint256 amount, address revealedAddr) internal view {
// 金額超過上限需要揭露
if (anonymousCap > 0 && amount > anonymousCap && revealedAddr == address(0)) {
revert RevealRequired();
}
// 揭露的地址帶有代碼 = CREATE2 碰撞攻擊
if (revealedAddr != address(0) && revealedAddr.code.length != 0) {
revert BurnAddressHasCode();
}
}

揭露模式重新鑄造流程(以 ZWERC20 為例):

// 1. 先從燃燒地址燃燒
if (revealedAddr != address(0)) {
_burn(revealedAddr, amount);
}
// 2. 然後進行正常重新鑄造(鑄造給接收者)
_executeRemint(to, id, amount, redeem, relayerFee);

效果:燃燒金額 → 鑄造金額(分配給接收者 + 中繼者 + 協議);總供應量(totalSupply)淨變化為 0

3.4 EXTCODESIZE 防護

有效的燃燒地址是來自 Poseidon 的隨機地址;它始終是一個 EOA(無字節碼)。如果 revealedAddr 擁有代碼,說明有人通過 CREATE2 碰撞在該處部署了合約——這是攻擊的直接證據。

if (revealedAddr.code.length != 0) revert BurnAddressHasCode();

成本:EXTCODESIZE 操作碼,約 100 gas。

4. 參考資料

https://ethresear.ch/t/dual-mode-remint-an-eip-7503-birthday-attack-mitigation-that-preserves-token-composability/24566