Nonce 與 API 錢包
背景
去中心化 L1 必須防止重放攻擊。當用戶籤署一筆 USDC 劃轉交易後,接收方不能將其多次廣播以掏空發送者的錢包。爲此,Ethereum 爲每個地址存儲一個 "nonce",它是一個從 0 開始的數字。每筆交易必須恰好使用 "nonce + 1" 才能被打包。
API 錢包
在文件中也稱爲 agent wallets。主帳戶可以授權 API 錢包代表主帳戶或其任何子帳戶進行籤名。
請注意,API 錢包僅用於籤名。要查詢與主帳戶或子帳戶關聯的帳戶數據,必須傳入該帳戶的實際地址。一個常見的錯誤是使用代理錢包地址查詢,這會導致結果爲空。
API 錢包的清理
在以下情況下,API 錢包及其關聯的 nonce 狀態可能會被清理:
- 錢包被註銷。當發送 ApproveAgent 操作註冊新的未命名 API 錢包時,現有的未命名 API 錢包會被註銷。當發送帶有相同名稱的 ApproveAgent 操作時,現有的已命名 API 錢包也會被註銷。
- 錢包過期。
- 註冊該代理的帳戶不再有資金。
重要提示: 對於以編程方式使用 API 錢包的用戶,強烈建議不要復用其地址。一旦代理被註銷,其已使用的 nonce 狀態可能會被清理。爲避免意外行爲,請在後續使用時生成新的代理錢包。例如,一旦 nonce 集合被清理,之前籤署的操作可能會被重放。
Hyperliquid 的 nonce 機制
Ethereum 的設計不適用於鏈上訂單簿。做市策略每秒可能發送數千個訂單和撤單。要求在區塊鏈上精確排序打包會破壞任何此類策略。
在 Hyperliquid 上,每個地址存儲最高的 100 個 nonce。每筆新交易的 nonce 必須大於該集合中最小的 nonce,且此前從未被使用過。nonce 按籤名者跟蹤:如果使用地址私鑰籤名,則爲用戶地址;如果使用 API 錢包籤名,則爲代理地址。
Nonce 必須在 (T - 2 days, T + 1 day) 範圍內,其中 T 是交易所在區塊的 unix 毫秒時間戳。
以下步驟可以幫助將自動化策略從中心化交易所遷移過來:
- 每個交易進程使用一個獨立的 API 錢包。請注意,nonce 按籤名者(即私鑰)存儲,因此由同一 API 錢包籤名的不同子帳戶會共享該 API 錢包的 nonce 跟蹤器。建議爲不同的子帳戶使用不同的 API 錢包。
- 在每個交易進程中,設定一個任務,每 0.1 秒定期批量處理訂單和撤單請求。建議將 IOC 和 GTC 訂單與 ALO 訂單分開批量提交,因爲驗證者會優先處理僅含 ALO 訂單的批次。
- 交易邏輯任務將訂單和撤單發送給批量處理任務。
- 對於每批訂單或撤單,獲取並遞增一個原子計數器,確保該地址的 nonce 唯一。如有需要,原子計數器可以快進到當前的 unix 毫秒時間戳。
此結構能夠容忍 2 秒內的亂序交易,對於地理位置靠近 API 伺服器的自動化策略應該足夠了。
對子帳戶和金庫用戶的建議
請注意,nonce 按籤名者存儲,即用於籤署交易的私鑰對應的地址。因此,建議每個交易進程或前端會話使用獨立的私鑰進行籤名。特別是,單個 API 錢包爲用戶、金庫或子帳戶籤名時,都共享同一個 nonce 集合。
如果用戶想並行使用多個子帳戶,更簡單的做法是在主帳戶下生成兩個獨立的 API 錢包,每個子帳戶各使用一個 API 錢包。這樣可以避免各子帳戶使用的 nonce 集合之間發生衝突。