# pERC20:私有代幣標準(草案)

本文為機器翻譯
展示原文

作者: Cyimon ( @Cyimon ) ·狀態:草案 ·類型:標準跟蹤 (ERC) · EIP: 8287 (PR) ·創建日期: 2026-06-09

描述: EVM 的可互換代幣標準,默認情況下是私有的。

討論: ethresear.ch #25089 · Ethereum Magicians #28702 ·實現: PERC20Labs/pERC20_


我們擴展了之前發佈的 pERC20 協議設計( Ethereum Magicians #28702 / ethresear.ch #25089 )。此次修訂的主要新增功能是通過ZIP-32子賬戶實現 ERC-20 認可的支出——包括approveallowancetransferFrom 。更新後的標準在功能上ERC-20完全兼容,但在字節上不兼容(ABI 不同,且不支持公開餘額)。

ERC-20 pERC20
name / symbol / decimals / totalSupply是的——公眾觀點相同鏈上
balanceOf是的——僅限持卡人掃描鏈下
transfer是的——私人聚會及金額鏈上
approve / allowance / transferFrom新增——已批准EOA支出者通過ZIP-32子賬戶進行支出;鏈上= transfer (不支持合約支出者)鏈下
mint / burn是的——常用擴展鏈上
Transfer / Approval事件省略(隱私)

以下是最新的 pERC20 標準:私有代幣標準


抽象的

pERC20是 EVM 的默認私有同質化代幣標準,是ERC-20的隱私版本。其底層採用Zcash協議規範中的 Orchard 屏蔽池模型。它保留了 ERC-20 的所有方法,但部分方法是私有的(僅限持有者訪問,鏈下),而非公開的鏈上讀取,並且transfer / approve / transferFrom在鏈上顯示為相同的transfer操作。請參閱下方的pERC20 接口

動機

以太坊的公共賬本使所有ERC-20餘額、轉賬和授權永久可見。隨著支付、工資、國庫和鏈上金融遷移到 L1 層,用戶和發行方需要的是私有的同質化代幣,而不僅僅是圍繞公共餘額的私密信息交流。

隱私問題越來越多地在協議層得到解決。例如, EIP-8182定義了一個協議層面的保護池:用戶可以存入公開的ETH或兼容的 ERC-20 代幣,在共享池內進行私密轉移,然後再提取回公開形式。該模型保護了現有的公共資產;但它並未定義如何發行從創建之初就具有私密性的代幣

pERC20填補了後一個空白。它是一個應用層代幣標準,用於原生私有同質化代幣:從一開始就以私有票據的形式通過approve / transferFrom進行鑄造、持有、轉移和使用,沒有公開的balanceOf階段,也不存入共享的屏蔽池。它定義了ERC-20的私有對應物——相同的方法界面,不同的開放程度——因此發行方可以立即發行私有資產,同時協議級隱私(例如 EIP-8182)也在同步發展。兩者是互補的,而非競爭的:EIP-8182 將公共資產私有化; pERC20定義了私有資產的發行。

規格

關鍵詞MUSTMUST NOTSHOULDMAY的解釋遵循 RFC 2119。Solidity 語法版本為0.8.20或更高版本。

底層協議

價值以屏蔽票據的形式存在,而非賬戶餘額。票據格式、作廢符、承諾樹、票據加密以及操作/捆綁結構均遵循Zcash協議規範中的Orchard 屏蔽池,並在此處改編為基於資產的 EVM 合約,且已通過 Groth16 驗證。下文未重複的字段級格式在參考實現部分中具有規範性。

pERC20接口

本節將所有 pERC20 接口集中列出,並標記每個接口是否對應於ERC-20標準接口。ERC -20yes = ERC-20 標準; extension = 通用擴展(鑄造/銷燬); no = pERC20 特有。層級on-chain = 合約 ABI; off-chain = 錢包/SDK(無合約方法)。

pERC20接口ERC-20開放性描述
name() / symbol() / decimals()是的鏈上民眾與 ERC-20 相同
totalSupply()是的鏈上民眾公共計數器( mint - burn
balanceOf(addr)是的鏈下私人的使用查看密鑰掃描Orchard紙幣;僅限持卡人使用
transfer(PrivacyCall)是的鏈上私人(參與方 + 金額)果園行動包
approve(spender, N)是的鏈下私密(關係已隱藏) ZIP-32子賬戶;資金 + 交付密鑰;鏈上提交為transfer(PrivacyCall)
allowance(owner, spender)是的鏈下私人的掃描子賬戶剩餘餘額
transferFrom(from, to, amount)是的鏈下私密(關係已隱藏)支出者在子賬戶中支出;鏈上提交為transfer(PrivacyCall)
mint(amount, PrivacyCall)擴大鏈上金額公開;收款人私密僅限發行方;果園行動 + totalSupply量增加
burn(amount, PrivacyCall)擴大鏈上公開金額;私人燃燒器持票人燒燬自己的票據;果園行動 + totalSupply減少
issuer()鏈上民眾代幣發行者地址
cmxFrozenRoot() / setFrozenRoot()鏈上公共根目錄;管理員寫入合規凍結記錄根
cmxRoot() / isValidAnchor() / isSpent() / treeSize()鏈上民眾果園承諾樹狀態

活動

pERC20事件ERC-20描述
Transfer(from, to, value)是的鏈下(省略)未公開;參與方和金額均屬私人信息。
Approval(owner, spender, value)是的鏈下(省略)未發行;將所有者與消費者關聯
NoteAdded / NoteConfirmed取代Transfer鏈上單張票據可觀察性
Mint / Burn擴大鏈上公開金額
Perc20Created / FrozenRootUpdated / BundleExecuted鏈上部署、合規性、捆綁元數據

鏈上操作不可區分。 transferapprovetransferFrom和撤銷操作的資金步驟在鏈上都是同一個調用: transfer(PrivacyCall) 。觀察者無法分辨正在執行的是哪個 ERC-20 操作。

原生不支持。ERC -20 的 ` approve(contractAddress, amount) `(合約自主調用transferFrom )沒有原生等效項:支出需要私鑰,而合約無法持有私鑰。參見原理。

合同接口

pERC20公開了一個鏈上 ABI( IPERC20 ;參見上文的pERC20 接口)。該表中標記為鏈下的方法沒有合約入口點;其行為在下文“方法語義”中指定。

interface IPERC20 {struct PrivacyCall { bytes actions; uint256[3] bindingSig; }struct BundleAction {bytes32 cmx;bytes encCiphertext;bytes outCiphertext;bytes32 epk;bytes32 nfOld; // nullifier of the consumed (or dummy) input notebytes32 anchor; // historical root of the consumed (or dummy) input notebytes proof;uint256[8] pubFields;uint256[3] spendAuthSig;}// ERC-20-aligned public viewsfunction name() external view returns (string memory);function symbol() external view returns (string memory);function decimals() external view returns (uint8);function totalSupply() external view returns (uint256);function issuer() external view returns (address);// Value-changing operations (private parties; see Method Semantics)function transfer(PrivacyCall calldata call) external returns (bool success);function mint(uint256 amount, PrivacyCall calldata call) external;function burn(uint256 amount, PrivacyCall calldata call) external;// Compliancefunction cmxFrozenRoot() external view returns (uint256);function setFrozenRoot(uint256 newRoot) external; // onlyAdmin// Note state machine (Orchard commitment tree)function cmxRoot() external view returns (bytes32);function isValidAnchor(bytes32 root) external view returns (bool);function isSpent(bytes32 nf) external view returns (bool);function treeSize() external view returns (uint256);event Mint(address indexed issuer, uint256 amount);event Burn(uint256 amount);event FrozenRootUpdated(uint256 oldRoot, uint256 newRoot);event Perc20Created(address indexed pool, address indexed issuer,string name, string symbol, uint8 decimals);event NoteAdded(bytes32 indexed cmx, bytes encCiphertext, bytes outCiphertext,bytes32 epk, bytes32 nfOld, bytes32 cvNetX);event NoteConfirmed(bytes32 indexed cmx, bytes32 newRoot, uint256 position);event BundleExecuted(uint256 valueBalance, uint256 amount, bytes32 recipientMeta);}

符合性:

  • transfer成功必須返回true
  • 核心包執行路徑絕對不能公開調用(供應不變式;見下文)。
  • 實現可以將 Solidity 拆分為多個合約(例如IPERC20 + 驗證器基礎),但可觀察的 ABI 和事件必須與上述統一接口匹配。
  • cmxRoot()是最新的承諾樹根; isValidAnchor(root)如果root曾經是活躍的則返回 true; isSpent(nf)公開空值集; treeSize()是插入的承諾數。

呼叫格式

每次更改值的操作都會提交一個PrivacyCall編碼一個或多個Orchard 操作Zcash協議規範):

  • actions = abi.encode(BundleAction[]) .
  • bindingSig = Schnorr 綁定簽名[Rx, Ry, s]證明值守恆。

每個BundleAction都是pubFields適用於 EVM 驗證的 Orchard 操作:一份輸出票據承諾 ( cmx ) 以及其(真實或虛擬)輸入的證明材料。pubFields 必須按以下順序排列(Orchard 操作的主要輸入):

指數場地角色
[0] anchor消耗輸入的默克爾根
[1] cv_net_x淨值承諾 X(具有約束力的簽名)
[2] cv_net_y淨值承諾 Y(具有約束力的簽名)
[3] nf_old消耗輸入的無效化
[4] rk_x隨機消費授權密鑰 X
[5] rk_y隨機消費授權密鑰 Y
[6] cmx輸出說明承諾
[7] rt_frozen合規性凍結根綁定

每個pubFields[i]必須< Fr ,其中Fr是驗證器(參考實現中為 BN254)使用的 SNARK 曲線的標量場模;否則,將返回錯誤( PubFieldOutOfRange )。實現必須通過ActionPubHash (Poseidon sponge)將這八個字段哈希到一個 Groth16 公共信號中,使其與電路的PubHashAction()相匹配。

綁定到調用數據字段。證明公共輸入必須與操作的頂級字段匹配;如果出現以下任何情況,實現必須回滾:

查看恢復
pubFields[0] == anchorisValidAnchor(anchor) BadAnchor
pubFields[3] == nfOld必須還原(參考實現: NullifierSpent
pubFields[6] == cmxcmx != 0 InvalidProof / ZeroCommitment
pubFields[7] == cmxFrozenRoot() BadFrozenRoot
spendAuthSig驗證pubFields[4]pubFields[5]是否在(nfOld, cmx, epk, encCiphertext, outCiphertext)範圍內。 BadSpendAuthSig

如果沒有pubFields ↔ calldata 相等性檢查,有效的證明可以用不同的nfOldcmx重放,繞過空值集或插入未經證明的承諾。

encCiphertext必須為 580 字節(Orchard 筆記outCiphertext + 收件人密鑰下的 AEAD 標籤)。outCiphertext 應為 80 字節(OVK 下的發送方自恢復)。更改筆記加密佈局的實現必須發佈此 ERC 的單獨變體。

在進行任何狀態變更之前,必須對所有操作無效符、承諾和操作的valueBalance驗證捆綁包級別的bindingSig (有關編碼,請參閱方法語義)。

注意加密和密鑰派生遵循Zcash協議規範中的 Orchard 筆記格式;確切的編碼在參考實現庫中。

方法語義

name / symbol / decimals / totalSupply

與 ERC-20 相同:公開的鏈上視圖。

transfer(PrivacyCall) → bool

使用Orchard票據作為輸入,並創建一個價值守恆的操作包( valueBalance == 0 )。發送者、接收者和金額必須保持私密。成功時返回true ;發出NoteAdded / NoteConfirmed ,而不是Transfer(from,to,value)

mint(amount, PrivacyCall) / burn(amount, PrivacyCall)

transfer相同的Orchard操作驗證路徑,並公開totalSupply統計:

  • minttotalSupply += amountonlyIssuer ); amount公開,接收方私有。鑄幣必須使用與transfer相同的錨點/無效符/支出授權路徑(無僅輸出分支)。電路必須將消耗的輸入限制為v = 0 ,以便該操作代表淨流入;合約不直接讀取票據價值。
  • burntotalSupply -= amount ;任何持有人均可銷燬自己的票據; amount公開,銷燬者私密。
手術valueBalance編碼
transfer 0
burn bit255 = 0,低位 = 金額
mint bit255 = 1,低位 = 金額

balanceOf (鏈下,私有)

只有持有者才能通過掃描NoteAdded事件、使用查看密鑰試解密Orchard筆記並排除已花費的無效符來計算餘額。鏈上沒有balanceOf ,也無法查詢第三方的餘額。

approve / allowance / transferFrom (鏈下語義;鏈上 = transfer

已批准的支出( approve / allowance / transferFrom )基於ZIP-32分層賬戶:每個EOA 支出者都會獲得一個專用的子賬戶( account_S ),該子賬戶擁有自己的支出密鑰和查看密鑰,並與所有者的主賬戶以及所有其他支出者進行加密隔離。ZIP -32定義了密鑰派生;此 ERC 將 ERC-20 的approve / transferFrom映射到 ZIP-32,具體如下:

  1. approve(spender, N) — 所有者創建一個未使用的 ZIP-32 子賬戶,通過transfer(PrivacyCall)向其充值N ,並將該子賬戶的支出密鑰交付給 EOA 支出者(鏈下加密)。鏈上操作:一次transfer
  2. allowance(owner, spender) — 該子賬戶的剩餘餘額,使用子賬戶查看密鑰掃描。無鏈上映射。
  3. transferFrom(owner, to, amount) — 支出者從子賬戶支出to目標賬戶;找零返回到子賬戶。鏈上:一次transfer
  4. approve(spender, 0) / revoke — 所有者通過transfer將子賬戶退回。

限額由子賬戶的實際票據餘額決定,而非鏈上計數器。錢包區分“自有”資產和“限額”資產的方式,是依據解密票據的查看密鑰,而非鏈上標記。

執行要求

鏈上狀態機遵循 Orchard 屏蔽池( Zcash協議規範)。實現必須:

  • 維護一個無效化符集;同一個無效nf不能使用兩次。
  • 維護一個僅追加的承諾樹;可通過isValidAnchor查詢歷史根節點。
  • 驗證 Groth16 證明、支出認證和綁定簽名,以及所有 pubFields 綁定檢查(不僅僅是pubFields[7] )。
  • 拒絕重複或零承諾;拒絕空操作數組;限制每次調用的操作數( maxActions ,一個有限的可配置正界限)。
  • 僅通過mint / burn / transfer公開價值變更(沒有公共捆綁包入口點)。
  • 在部署時發出Perc20Created一次(建議進行工廠部署,但並非必須)。

合規性。cmxFrozenRoot cmxFrozenRoot()是鏈下黑名單 SMT 的根;該電路用於證明已花費的筆記不屬於該黑名單setFrozenRoot僅限admin使用;初始根0表示黑名單為空。實現可以在更新後的短暫寬限期內接受緊鄰的前一個根,以避免正在進行的證明被擱置。

理由

  • Orchard ZK-UTXO 模型。註釋、無效化符和承諾樹遵循Zcash協議規範;此 ERC 定義了私有代幣接口和在 EVM 上的每個資產的部署。
  • 私有 ERC-20 代幣,並非不同的資產。方法表面相同;隱私改變的是開放性(公開查看 vs 私密查詢 vs 不可區分的傳輸),而不是用戶意圖。
  • 所有資金轉移只需一次鏈上操作。合併transfer / approve / transferFrom會移除 ERC-20 不可避免的授權元數據洩露。
  • 通過ZIP-32子賬戶批准支出。每個 EOA 支出者都會獲得一個獨立的層級賬戶,而不是鏈上allowance映射;參見方法語義。
  • 無需approve(contract)合約沒有私鑰;將支出密鑰放在鏈上會使其暴露給所有人。可編程的私有支出(謂詞授權的票據、MPC託管)是未來的工作,不屬於本次ERC的範圍。
  • 錢包行為不在鏈上ABI的範圍內。子賬戶佈局、加密密鑰交付和票據掃描屬於錢包/SDK的職責範圍;請參閱參考實現。

向後兼容性

pERC20具備ERC-20 的所有功能,但與字節不兼容:沒有公開的balanceOf屬性,沒有鏈上allowance ,沒有approve / transferFrom ABI,也沒有Transfer / Approval事件。現有的 ERC-20 索引器和可組合合約在沒有隱私保護錢包/SDK 的情況下無法驅動 pERC20。

可選的bridgeOut到公共 ERC-20 孿生服務器可能會在出口處終止隱私;本提案不要求這樣做。

測試用例

參考實現庫包含:

  • 鑄造單元測試( test/PERC20Test.t.sol ):構造函數保護、鑄造/銷燬/轉移會計、供應不變量。
  • 端到端測試( test/PERC20E2E.t.sole2e/ ):針對已部署的PERC20的真實 Groth16 證明,涵蓋鑄造、轉移、銷燬和approve / transferFrom流程。

參考實現

代碼

參考實現: PERC20Labs/pERC20_

  • 規範性資產合約: contracts/ptoken/PERC20.solIPERC20 )。
  • 加密和錢包格式(密鑰派生、 perc1地址、筆記加密、無效化器、 approve打包):參考庫和 SDK 在同一個存儲庫中。

相關標準和協議

  • EIP-20 :代幣標準pERC20映射到的公共可互換代幣接口。
  • Zcash協議規範:Orchard 屏蔽池 — 注意承諾、無效化器、筆記加密和操作結構,此處針對 EVM Groth16 驗證進行了調整。
  • ZIP-32 :受保護的分層確定性錢包——用於在approve / transferFrom中按消費者子賬戶的分層賬戶派生。

安全考量

  • 雙花保護:空值設置 + 正確的nf推導。每個pubFields[i]必須< Fr (否則nf + Fr會重用具有不同isSpent鍵的證明); pubFields[0][3][6]必須分別等於anchornfOldcmx (否則有效的證明可以綁定到不同的 calldata)。
  • 供應不變性:價值僅通過mint / burn / transfer改變;核心執行路徑不得公開調用。
  • 價值守恆:在狀態突變之前驗證結合特徵。
  • 重放保護:sighash 綁定chainId 、合約地址和所有nf / cmx
  • 子賬戶支出密鑰:用於approve密鑰必須僅以密文形式出現;絕不能存儲在合約中。
  • 合規權限setFrozenRoot是一個高信任度的管理員角色;應該使用多重簽名/時間鎖。

隱私考量

  • 操作應該通過中繼器提交,以隱藏提交者的EOA。
  • mint / burn amounttotalSupply是公開的;轉賬金額和approve關係是私密的。
  • approve / transferFrom在鏈上與transfer無法區分(相同的transfer(PrivacyCall)選擇器); mint / burn是具有公開數量的獨立函數。
  • 試解密是收款的信任邊界:僅憑NoteAdded事件無法證明付款;電路不會驗證encCiphertext是否與cmx匹配。
  • setFrozenRoot允許管理員通過鏈下黑名單凍結已識別的筆記;這是對完全不信任的一種明確的合規性權衡。

版權

通過CC0放棄版權及相關權利。

請引用此文檔:Cyimon,“ERC-8287:私有代幣標準”,以太坊改進提案,2026 年 6 月。


來源
免責聲明:以上內容僅為作者觀點,不代表Followin的任何立場,不構成與Followin相關的任何投資建議。
喜歡
收藏
評論