JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

跨鏈橋如何把代幣搬到別條鏈:鎖定與鑄造

代幣其實無法離開它出生的那條鏈——於是跨鏈橋在一邊鎖住真幣、在另一邊鑄出一張借據。我們會親手把這台機器組起來,用數字與程式碼證明它的錨定,並追問唯一要緊的問題:鑰匙在誰手上?

替你的硬幣領一張寄物牌

想像你穿著一件厚重的冬大衣走進劇院。你沒辦法把它帶進觀眾席,於是交給寄物櫃台,櫃台給你一張寫著號碼的小牌子。那張牌子不是你的大衣——它是一張對大衣的提取權。你可以把它放進口袋、甚至交給朋友,誰拿著牌子,誰之後就能上前領回那件真大衣。大衣從沒移動過,移動的只是那張提取權。

跨鏈橋做的事情正是如此。一枚 比特幣只活在比特幣鏈上——它的存在就是比特幣帳本裡的一筆紀錄,你發給 以太坊的任何訊息都無法把它瞬移過去。於是跨鏈橋把你真正的 BTC 鎖在比特幣鏈上(寄放的大衣),並在以太坊上鑄出一枚對應的代幣(那張牌子)。這枚鑄出的代幣叫做包裝代幣,而它是一張借據:它之所以有價值,純粹是因為你相信能把它交回去、把本尊贖回來。

鎖定與鑄造,一步一步來

鎖定與鑄造的循環有四個動作,而且來回是對稱的:鑄造受到「鎖定」的把關,解鎖受到「燒毀」的把關。沒有任何東西憑空生出,橋所掌管的任何資產也絕不會同時出現在兩個地方。

  1. 鎖定。 你把真正的代幣送進橋在 A 鏈上的金庫。金庫不會把它銷毀——而是把它留置作為抵押,並發出一個 `Locked` 事件,記下金額以及你在 B 鏈上的位址。
  2. 鑄造。 鏈外的監看者(轉發者/驗證者集合)看到那個 `Locked` 事件,一旦確信它已最終定案,便指示 B 鏈上的包裝代幣合約 `mint`(鑄造)給你等量的借據代幣。
  3. 燒毀。 之後,當你想回家,便在 B 鏈上呼叫 `burn`。包裝代幣被銷毀——供給量隨之下降——並發出一個 `Redeem` 事件,記下金額以及你希望本尊送回哪裡。
  4. 解鎖。 橋向 A 鏈金庫證明那筆燒毀確實發生,金庫便把你抵押的本尊代幣放出。大衣從寄物間取回,牌子當場銷毀。

讓整件事保持誠實的唯一不變量,是供給守恆:在每一個瞬間,B 鏈上流通的包裝代幣數量,都必須等於 A 鏈金庫裡鎖住的真代幣數量。一開始鎖了 1,000 BTC、鑄了 1,000 wBTC。有人再存入 1 BTC → 橋鑄出 1 wBTC → 現在是 1,001 對 1,001。有人燒掉 5 wBTC → 橋放出 5 BTC → 現在是 996 對 996。鑄造量 == 鎖定量,永遠如此。一旦鑄造量超過鎖定量,這張借據就「抵押不足」了——而那正是盜竊或漏洞在鏈上留下的簽名。

包裝代幣的價值,全看背後的抵押撐不撐得住

現實世界最經典的例子是 WBTC:真正的比特幣被託管保存,而一枚同名的 ERC-20 包裝資產在以太坊上被鑄出,好讓 BTC 的價值能進入以太坊的 DeFi 使用。由於那些 BTC 存放在公開可查的位址,任何人都能直接在比特幣鏈上稽核儲備,並核對它是否與以太坊上的 WBTC 供給相符——這就是儲備證明。錨定並非魔法;它就是這份可稽核的 1:1 抵押,加上「可以贖回」的權利。

這裡正是「借據」這個概念最鋒利的地方。假設有 1,001 wBTC 在流通,但金庫被掏空、背後只剩下約 0 BTC。此時每一枚 wBTC 都成了對「無物」的提取權,市場便把它重新定價、趨近於零——包裝代幣脫鉤了。這並非空談:當某座大型橋被駭、損失了 12 萬枚包裝 ETH 時,它的支持者不得不注入 12 萬枚真 ETH 來補滿儲備、撐住錨定,原因正是——一枚沒有抵押的包裝代幣,不過是一張領取不到大衣的廢牌。持有包裝代幣,就等於相信另一端的鎖定是真的、而且會一直是真的。

用程式碼看跨鏈橋的兩半

我們用一座最精簡的 EVM 對 EVM 橋把它講具體(例如把 L1 上的某個 ERC-20 鎖起來、好在 L2上使用——官方橋本質上就是這麼做的)。A 鏈擺金庫,B 鏈擺包裝代幣。把它們當成一對來讀:金庫從不燒毀,包裝版從不託管。

// ===== Chain A: lock real tokens; never destroy them =====
contract BridgeVault {
    IERC20  public immutable token;
    address public immutable operator;        // who is allowed to authorize unlocks
    mapping(bytes32 => bool) public processed; // replay guard for proven burns

    constructor(IERC20 _token, address _operator) {
        token = _token; operator = _operator;
    }

    // 1) Deposit -> tokens are LOCKED here as collateral.
    function lock(uint256 amount, address recipientOnB) external {
        token.transferFrom(msg.sender, address(this), amount);
        emit Locked(msg.sender, recipientOnB, amount);
    }

    // 4) After a valid burn on chain B is proven, release the originals.
    function unlock(bytes32 burnId, address to, uint256 amount) external {
        require(msg.sender == operator, "not authorized");
        require(!processed[burnId], "replay");   // each burn redeems exactly once
        processed[burnId] = true;
        token.transfer(to, amount);
        emit Unlocked(burnId, to, amount);
    }

    event Locked(address indexed from, address recipientOnB, uint256 amount);
    event Unlocked(bytes32 indexed burnId, address to, uint256 amount);
}
A 鏈——寄物間。代幣經由 lock() 進入,且只能經由 unlock() 離開,而 unlock() 只有 operator 能呼叫。
// ===== Chain B: mint the IOU on deposit, burn it on exit =====
contract WrappedToken is ERC20 {
    address public immutable bridge;          // the only minter

    constructor(address _bridge) ERC20("Wrapped TOKEN", "wTKN") {
        bridge = _bridge;
    }
    modifier onlyBridge() { require(msg.sender == bridge, "not bridge"); _; }

    // 2) Called after the relayer proves a Locked event on chain A.
    function mint(address to, uint256 amount) external onlyBridge {
        _mint(to, amount);                    // supply rises by exactly `amount`
    }

    // 3) Burn to go home; the relayer carries this proof back to chain A.
    function burn(uint256 amount, address recipientOnA) external {
        _burn(msg.sender, amount);            // supply falls by exactly `amount`
        emit Redeem(msg.sender, recipientOnA, amount);
    }

    event Redeem(address indexed from, address recipientOnA, uint256 amount);
}
B 鏈——那張牌子。mint() 是供給量唯一的增長途徑,burn() 是唯一的縮減途徑。把兩份合約對照著看,供給守恆的不變量就一目了然了。

盯著這兩份合約看,你會發現整座橋的安全性,最終都歸結為兩種特權:誰能在 B 鏈呼叫 `mint`,以及誰能在 A 鏈呼叫 `unlock`——兩者都由同一個 `operator`/`bridge` 權限把關。鎖定的那套密碼學是簡單的部分;那個 `operator` 才是柔軟的腹部。而那個權限究竟是什麼——一組多簽、一個驗證者集合、一個輕用戶端、還是一份 zk 證明——正是下一篇的主題,也正是幾乎每一座真實的橋流血的地方。

鑰匙在誰手上?託管與非託管

在我們的程式碼裡,鎖定的代幣存在合約之內,但仍然得有某個東西被信任,去扳動 `mint` 與 `unlock`。人們替橋分類的第一條軸線,就是鎖定資產的保管權落在哪裡

  1. 託管式(受信任)。 一個具名的實體保管真資產,並握有授權鑄造的鑰匙——以 WBTC 來說,由託管商保管比特幣、由商戶網路負責鑄造/燒毀。你信任一個鏈外組織不會捲款潛逃、不會被駭、也不會被強制脅迫。這就是 受信任橋:簡單、在法律上可問責,但有一個「人形」的單點故障。
  2. 非託管式(合約保管)。 沒有任何單一個人握著幣;它們存在一份智慧合約裡,放行規則由程式碼決定。但要看仔細——「非託管」並不等於「無信任」。如果 `mint`/`unlock` 是由 N-of-M 的多簽或一個驗證者集合授權,你不過是把保管權分散給一個委員會罷了。攻破這個委員會,合約照樣聽命。
  3. 信任極小化。 最強的設計,是讓 `unlock` 變成「可證明的」而非「被授權的」:一座 無信任橋會驗證一份輕用戶端證明、或一份「燒毀確實在另一條鏈上發生」的有效性證明,於是安全性歸結到兩條鏈各自的共識,而非一個額外的委員會。威力強大,但建造繁重、驗證時的 gas 也昂貴。

三種跨鏈橋家族(外加一種不算橋的)

鎖定與鑄造是原型,但它不是唯一的管路。知道它屬於哪個家族,你就會知道在彼端真正收到的是什麼——一張包裝借據、一枚原生代幣,還是別人的庫存。

  1. 鎖定與鑄造(我們剛搭的):在 A 鎖定,在 B 鑄出一張包裝借據;在 B 燒毀以解鎖 A。目的端的代幣並非官方資產——它是一張橋專屬的提取權,而不同的橋會鑄出彼此互不通用的不同版本。
  2. 燒毀與鑄造 當同一個發行方掌控著每條鏈上的該代幣,你就能完全跳過借據——在 A 燒掉原生 USDC、在 B 鑄出原生 USDC(Circle 的 CCTP 就是這麼運作)。兩端都是本尊,因此沒有包裝脫鉤的風險;信任轉移到發行方對「燒毀已發生」的背書上。
  3. 流動性網路(鎖定與解鎖): 兩條鏈上都備有資產的資金池。你在 A 存入、從 B 的資金池中提出貨真價實的代幣——速度快、拿到的是官方資產,但受限於可用流動性,且資金池必須有人注資與再平衡。

至於那種不算橋的:原子交換。兩個各自在相對的鏈上已持有一枚幣的人,可以不靠任何橋、金庫或包裝代幣就完成交易,靠的是兩份雜湊時間鎖合約。Alice 把她在 A 鏈的幣鎖在一個雜湊之後;Bob 把他在 B 鏈的幣鎖在同一個雜湊之後;誰揭露祕密原像去領取其中一邊,數學上就同時把它揭露給了另一邊,於是兩條腿要嘛雙雙完成、要嘛在逾時後雙雙退款。它優雅地信任極小化——但它只能在「都有意願」的對手方之間交換既有資產;它無法在一條根本沒有 BTC 的鏈上,憑空造出一個 BTC 的代表物。正是這個侷限,才讓鎖定與鑄造的橋有存在的理由。

你跨鏈帶過去的,到底是什麼

退一步看,這幅圖像很誠實、卻也令人不太舒服。一座鎖定與鑄造的橋並不搬動你的資產;它把本尊凍結,並在別處發行一張合成的提取權。那個合成物之所以是錢,僅僅在「鎖定完好、贖回權被兌現」的前提下成立。你在兩條鏈之上,又疊加了一個新的依賴:橋本身。

所以帶進下一篇的箴言是:一枚包裝代幣是一張借據,借據是一個承諾,而承諾的強度,只取決於那個能撕毀它的人。你現在懂了這台機器——鎖定、鑄造、燒毀、解鎖,以及把它們綁在一起的供給守恆不變量。接下來,我們會打開決定「誰能授權這台機器」的信任模型,並逐行走過史上最大的幾起跨鏈橋駭客事件,看清究竟是哪個假設崩了。