Albert.Lin

Posted on Sep 21, 2022Read on Mirror.xyz

Zerion 如何利用 Genesis Card NFT 實現跨鏈 (on Polygon) 減免手續費

TLDR

Zerion 是利用鏈下判斷該帳戶是否有 Genesis NFT。若確認有擁有 Genesis NFT,Zerion的 Signer 去簽署一筆 fee = 0 的簽章並放在交易中。當交易送到合約的時候會去判斷簽章是否為 Zerion Signer 所簽。若為 Zerion Signer 所簽就不收費。

Trace Flow

在呼叫 Zerion swap token 的時候會去呼叫 Zerion Routerexecute() external function。

因為我們想要知道 protocol fee 在什麼時候被收取,所以我們直接跳到最後 return execute(input, output, swapDescription) 這個 internal function 去看發生什麼事。

execute() internal function 中,我們往下走在 #196 行會發現這一行程式碼 Base.transfer() 。這行程式碼就是把 fee 傳送到 Zerion MultiSig 中。

fee 的數量就是 protocolFeeAmount 所記錄的數值。哪這個數值是在哪邊決定的呢?往上面的程式碼找尋可以發現 protocolFeeAmount 是從 getReturnedAmounts() 所決定。

getReturnedAmounts()#496 是決定 protocolFeeAmount 的數字怎麼來。可以發現它是由 totalFeeAmount * protocolFee.share 所決定。

我們知道若 Sender 持有 Genesis Card NFT 可以擁有 Zero Fee 的減免。protocolFeeAmount 變成 0 條件有兩個。 totalFeeAmount 等於 0 或protocolFee.share 等於 0 (或同時為 0 )。 於是我找了一個擁有 Genesis Card NFT 且 fee 為 0 的 transaction 來一探究竟。 使用 Tenderly 發現他的 protoclFee.share 就是帶 0。由此判斷是一開始帶進來的參數就指定了 protocolFee.share來決定這次 protocol fee 要收多少。

此時出現一個疑問。若 protocol fee 是由參數帶進來,那我們不就可以任意決定 protocol fee 了嗎?這時候讓我們回頭看到一開始的 execute() extneral function。

裡面跟 Fee 有關的檢查是 validateProtocolFeeSignature() 這一個 function。接下來我們就來分析裡面做了什麼事情。

第一個部分是去檢查這次交易有沒有包含 protocolFeeSignature。若沒有(length會等於0)就單純檢查收 fee 的對象和 protocolFee.share 是否跟 contract 預設的一樣。

若有帶 protocolFeeSignature ,就去呼叫 hashProtocolFeeSignatureData() 取得 signatureData。

hashProtoclFeeSignatureData 就是把部分參數包含 swapDescriptiondealine等取 hash 值。這個 hash 就是 Signature 所簽的 data。

得到了 signature data 之後就去呼叫 isValidSignatureNow() 來比對簽章是否正確。可以注意 isValidSignatureNow() 其中一個參數是 getProtoclFeeSigner() ,這個是 Zerion Router 合約裡面所定義的 signer。

isValidSignatureNow() 裡面就做兩件事情。

  1. 利用剛剛得到的 hash 和 signature 來還原簽署的 address (就是裡面的 recovered)。比對 recoveredsigner 是否相同。若相同就代表這是由 Zerion signer 所簽署,確認 swapDescription 裡面所帶的 protocolFee 相關資訊是被 Zerion Signer 所認可。
  2. 下方的 staticall 是支援若 Zerion Signer 是合約而非單純的 EOA。因為合約沒有 key,所以無法簽署簽章。所以利用 ERC1271 的方式來實現合約簽章。詳細內容可以參考這篇文章

若確認簽章無誤,最後就檢查是否超過簽署的 dealine。

通過 deadline 的檢查後,就會依照 protocolFee 所記錄的資訊(包含 reciver 和 fee amount)去收取 protocol fee。

Takeaway

因為目前跨鏈的機制還尚未成熟,所以 Zerion 利用一個 signer 的角色來判斷該筆交易是否需要收 protocol fee。這樣的機制或許不是那麼去中心化,但卻是一個比較合理的做法。這樣的方式可以快速運用在不同的鏈上,而不需要考慮鏈與鏈之前該如何溝通。使用者也只需要在某個鏈上擁有該 NFT 就好,不需要每個鏈都有。缺點仍是中心化,若之後 Zerion 想要修改規則,變成改收 1% 的 protocol fee,一般使用者也只能乖乖接受(Zerion Signer 可以簽他們想要簽的任何交易)。在過渡時間這尚可是一個可以接受的方式,期待未來跨鏈機制的成熟,就不需要利用這個中心化的方式來做,而可以真的直接讀取鏈上的資訊來收費。

PolygonNFT