走出「誰擁有它」
一位插畫家鑄造了一件作品,以 1 ETH 賣出,並在上架資訊裡寫上「10% 權利金」。一年後同一張圖以 80 ETH 轉手。她從這筆暴利分到多少?常常是零。不是因為有人駭了她的合約——而是因為在多數鏈上,權利金是一種禮貌性的請求,而非協定會強制執行的規則。
這一階前面的指南教過你代幣是什麼:ERC-20 的餘額、ERC-721 NFT 那獨一無二的 tokenId、ERC-1155 的多代幣效率,以及一個 NFT 的圖片究竟存在哪裡。這些標準都在回答同一個問題——誰擁有什麼,又如何轉移? 這最後一篇談的是三片改寫這個問題的前沿:試圖永遠跟著代幣走的金錢(EIP-2981 權利金)、根本拒絕轉移的所有權(靈魂綁定代幣),以及錢包本身變成你能程式化的智慧合約(ERC-4337 帳戶抽象化)。
EIP-2981:鏈能描述、卻無法強制的權利金
EIP-2981 刻意做得極小。它只新增一個唯讀函式 `royaltyInfo`,輸入一筆售價,回答兩件事:該付給誰、以及付多少。就這樣。它不搬動任何金錢、不碰任何餘額——它只是一張市集可以讀取的標籤。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol";
contract ArtNFT is ERC721, IERC2981 {
address public royaltyReceiver;
uint96 public royaltyBps; // basis points: 500 = 5%
constructor(address receiver, uint96 bps) ERC721("ArtNFT", "ART") {
royaltyReceiver = receiver;
royaltyBps = bps; // e.g. 500 for 5%
}
// EIP-2981: given a sale price, report who is owed how much.
// NOTE: this only *reports*. It never receives or forwards funds.
function royaltyInfo(uint256 /*tokenId*/, uint256 salePrice)
external view returns (address receiver, uint256 royaltyAmount)
{
return (royaltyReceiver, (salePrice * royaltyBps) / 10_000);
}
// Tell the world (and marketplaces) we implement the standard.
function supportsInterface(bytes4 id) public view override returns (bool) {
return id == type(IERC2981).interfaceId || super.supportsInterface(id);
}
}這裡有個界定整個主題的關鍵:`royaltyInfo` 是個 view 函式。當買家轉移一個 NFT 時,ERC-721 標準裡沒有任何東西會去呼叫它。是市集合約必須選擇去讀那個數字、拆分款項、把該給的份額送給創作者。如果它不做,轉移照樣成功,創作者卻一毛都拿不到。權利金是鏈上真實存在的資料,卻附著在一筆可能永遠不會照藝術家所願發生的交易上。
這並非假設。2022–2023 年間上演了一場「權利金戰爭」:像 Blur 這樣的交易場所以「創作者費用可選」為競爭手段,許多系列的實際權利金支付一路崩向零。OpenSea 以一套 Operator Filter Registry(運營者過濾登錄) 反擊,封鎖向不尊重權利金之市集的轉移——然後在 2024 年 8 月,當整個生態系不滿這種強硬作風時,悄悄將其棄用。如今真心想要強制執行的專案,會轉向像 Limit Break 的 ERC-721-C 這類設計:讓每一次轉移都通過一個鏈上驗證器把關,而那個驗證器可以要求權利金必須付清。
靈魂綁定代幣:賣不掉的所有權
現在把問題反過來。權利金之所以棘手,是因為轉移太自由。那如果轉移正是你不想要的呢?一張大學文憑、一枚「完成此課程」徽章、一張出席證明、一段信用紀錄——這些只有黏在你身上才有意義。一張能向陌生人買來的文憑毫無價值。這正是靈魂綁定代幣(SBT)的構想:綁定在單一帳戶上、不可轉讓的代幣。
這個詞出自 Vitalik Buterin(2022 年 1 月的一篇部落格文章,借用了《魔獸世界》的用語),並在 2022 年 5 月的論文《Decentralized Society: Finding Web3's Soul(去中心化社會:尋找 Web3 的靈魂)》中加以延伸。關鍵在於:你不需要一個全新的標準就能做出一個——你拿一個普通的 ERC-721,再移除轉移的能力即可。在 OpenZeppelin v5 合約裡,鑄造、轉移與銷毀全都匯流到單一的內部掛鉤 `_update`,所以一次覆寫就能把代幣封死:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
/// A credential that can be MINTED to a wallet and BURNED by it,
/// but never TRANSFERRED to another wallet.
contract Credential is ERC721 {
error TokenIsSoulbound();
// EIP-5192: a minimal interface so wallets/marketplaces know it's locked.
event Locked(uint256 tokenId);
constructor() ERC721("Credential", "CRED") {}
function locked(uint256) external pure returns (bool) {
return true; // always locked
}
// In OZ v5, mint/transfer/burn all route through _update.
// from == 0 -> mint (allowed)
// to == 0 -> burn (allowed: you may give it up)
// otherwise -> transfer (blocked)
function _update(address to, uint256 tokenId, address auth)
internal override returns (address)
{
address from = _ownerOf(tokenId);
if (from != address(0) && to != address(0)) revert TokenIsSoulbound();
return super._update(to, tokenId, auth);
}
}真實的用途已經出現:POAP(你出席過某活動的證明)、鏈上憑證與 KYC 認證、類似 Gitcoin Passport 的信譽,以及代幣門禁式的存取——而這把「鑰匙」沒辦法直接賣給黃牛。SBT 也暗示了今日 DeFi 做不到的一件事——低抵押借貸:用一段不可轉讓的信用信譽(而不只是鎖住的資本)來為貸款背書。
帳戶抽象化:當錢包變成智慧合約
每一個一般的 以太坊錢包——你 MetaMask 種子片語背後的那個——都是外部擁有帳戶(EOA)。它只有一條硬寫死的規則:一筆交易要有效,必須帶有來自單一私鑰的一個 ECDSA 簽章。那把唯一的金鑰就是你的全部身分。弄丟它,錢就永遠沒了。沒有「忘記密碼」、沒有消費上限、沒有「需要我三把金鑰中的兩把」,而且你永遠得自己持有 ETH 來付 gas。簽章規則被烙進了協定裡;你改不了它。
帳戶抽象化問的是:如果「這筆交易有效嗎?」的規則本身,是一段由你撰寫的程式碼呢?ERC-4337 正好實現了這件事——而最巧妙的地方在於,它做到這點完全不必更動以太坊的共識。它不去碰協定,而是在協定之上、用智慧合約搭起一套平行的交易系統。你的錢包變成一個智慧帳戶:一個自己決定「什麼才算有效動作」的合約。
讓這套機制運轉的,有四個零件:
- UserOperation(使用者操作)——不是一筆普通交易,而是一個描述你的智慧帳戶想做什麼的偽交易物件。你用帳戶自選的方式簽署它(一把金鑰、多簽、一把 passkey……),再把它丟進一個獨立的「替代記憶池」。
- Bundler(打包者)——一個角色(很像區塊建構者),它盯著替代記憶池、蒐集許多 UserOperation,把它們包進一筆普通的鏈上交易。打包者先墊付 gas,事後再獲得補償。
- EntryPoint(進入點合約)——一個經過稽核、所有智慧帳戶都信任的單例合約。它分兩階段(先驗證、再執行)跑每個 UserOperation,並負責把錢補償給打包者,這樣個別帳戶就不必自己處理。
- Paymaster(代付者)——一個選用的合約,它同意為你的操作支付 gas:它可以完全贊助使用者(無 gas 入門),或讓他們改用像 USDC 這樣的 ERC-20 來付費,而非用 ETH。
拆開一個 UserOperation
一個 UserOperation 像是交易那位野心勃勃的表親。它帶著一般的 gas 與 nonce 欄位,但有兩樣東西特別突出:一個能在首次使用時部署帳戶的 `initCode`(透過 CREATE2,所以位址在合約存在之前就已知道——所謂「反事實」部署),以及一個協定從不檢查的 `signature`。取而代之,是由你帳戶自己的程式碼來驗證它。
// The pseudo-transaction a smart account signs (ERC-4337 v0.6).
struct UserOperation {
address sender; // the smart account itself
uint256 nonce; // replay protection (per-account)
bytes initCode; // deploys the account on first use (CREATE2)
bytes callData; // what the account should actually do
uint256 callGasLimit;
uint256 verificationGasLimit;
uint256 preVerificationGas;
uint256 maxFeePerGas;
uint256 maxPriorityFeePerGas;
bytes paymasterAndData; // optional sponsor (paymaster) + its data
bytes signature; // checked by the ACCOUNT, not the protocol
}
// During the verification phase the EntryPoint calls this on your account.
// Return 0 to accept; this is where you put YOUR rules.
interface IAccount {
function validateUserOp(
UserOperation calldata userOp,
bytes32 userOpHash,
uint256 missingAccountFunds // top-up the account owes the EntryPoint
) external returns (uint256 validationData);
}EntryPoint 以兩個嚴格的迴圈處理一個批次。首先是驗證迴圈:對每個操作呼叫 `validateUserOp`,依你的自訂規則檢查簽章與 nonce,並向 EntryPoint 預付一筆 gas。只有當每個操作都通過後,執行迴圈才會去跑每個操作的 `callData`。把驗證與執行拆開,正是讓打包者能安全地把陌生人的操作批在一起的關鍵:一個壞簽章在第一階段就被免費駁回,不會進到第二階段那些昂貴的工作。
帳戶抽象化解鎖了什麼——又付出什麼代價
一旦「有效」變得可程式化,那些長年的錢包痛點就變成你能交付的功能:
- Gas 贊助——由代付者支付 gas,讓新使用者在身上一點 ETH 都沒有的情況下就能簽出第一個動作,或用 USDC 付費。入門不再需要先跑去交易所,只為了買「付 gas 的錢」。
- 社交復原——指定一群守護者(朋友、裝置、某個機構),在你弄丟金鑰時由他們一起替你輪換簽章金鑰。一個社交復原錢包把「弄丟種子片語=永遠失去資金」變成一件可以挺過去的事。
- 批次處理與 session 金鑰——一鍵完成「先批准、再兌換」,而非兩筆交易;或授予一款遊戲一把受限的「session 金鑰」,讓它在一小時內做些小額操作,而不必為每一步重新簽名。
- 自訂簽章——驗證手機的 passkey(secp256r1)而非種子片語,讓錢包用起來像 Face ID,而不是 24 個嚇人的單字。
這一切都不是免費的。智慧帳戶比 EOA 耗更多 gas(每個操作都多了額外的合約呼叫),替代記憶池/打包者這套基礎設施比以太坊基礎層更年輕、也更中心化,而代付者是一個你得仰賴它持續贊助的受信任方——而且若它贊助得不謹慎,還會成為被惡意消耗的目標。再加上 EOA 至今仍是絕大多數的錢包,所以 dApp 在未來數年內都得同時支援這兩個世界。
把這片前沿串起來
退一步看,這三片前沿彼此押韻。權利金想讓金錢跟著一個能自由流動的代幣走,卻發現沒有強制執行,標準就只能「建議」。靈魂綁定代幣想讓一個代幣永遠不移動,卻發現把它釘在單一位址上,會生出新的隱私與復原問題。而帳戶抽象化回答了復原問題——還不只如此——靠的是讓帳戶本身可程式化,於是錢包不再是一把脆弱的單一金鑰,而成為一份帶著規則的合約。
這也是整個這一階的主軸:一個代幣標準從來不只是一種資料格式——它是一份微型社會契約,規範著錢包、市集與其他合約可以對彼此做出哪些假設。從這裡開始,階梯轉向這些代幣在何處大規模地生存與交易:你現在已會撰寫的這些合約,正是後面的安全、DeFi 與擴容各階將要壓力測試、攻擊與優化的對象。