【技術分析】惡意 SPL 代幣識別指南
背景
在 EVM 生態上,存在各式各樣的 ERC20 代幣,因其實現方式有著極高的自由度,也催生了花樣繁多的惡意代幣。這些惡意代幣通常會在代碼中實現一些惡意的邏輯(禁止用戶賣出,特權鑄造或銷毀等),其目的就是騙取用戶買入后把用戶的錢卷走。
誒!為了解決這個情況,Solana 官方提供了官方的代幣模板。你要在 Solana 上發行貨幣,只需要填寫一些基本信息,不需要編寫代幣邏輯,即可部署一個 SPL 代幣。
但是,即使是這種情況, Solana 鏈上還是存在許多惡意代幣,各自用著不同的手法來坑騙代幣持有者。所以本篇文章嘗試著分析從哪些維度可以判斷一個 SPL/SPL2022 代幣是否存在安全隱患或惡意傾向。
有關 SPL 和 SPL2022 的背景與定義,讀者可閱讀官方文檔進行了解:https://spl.solana.com/token
SPL 代幣
SPL 文檔:https://spl.solana.com/token
SPL 代碼:https://github.com/solana-labs/solana-program-library/tree/master/token/program
SPL 代幣實現了 25 個指令,根據 instruction::TokenInstruction 將 SPL 代幣的指令根據功能進行分類總結:
- 初始化代幣鑄造:
InitializeMint,InitializeMint2- 初始化新的代幣鑄造賬戶。 - 初始化代幣賬戶:
InitializeAccount,InitializeAccount2,InitializeAccount3- 初始化新的代幣持有賬戶。 - 初始化多重簽名:
InitializeMultisig,InitializeMultisig2- 初始化多重簽名賬戶。 - 轉賬:
Transfer,TransferChecked- 在賬戶之間轉移代幣。 - 授權:
Approve,ApproveChecked- 授權委托人使用一定數量的代幣。 - 撤銷授權:
Revoke- 撤銷對委托人的授權。 - 設置權限:
SetAuthority- 更改鑄造或賬戶的權限。 - 鑄造代幣:
MintTo,MintToChecked- 鑄造新代幣到指定賬戶。 - 銷毀代幣:
Burn,BurnChecked- 從賬戶中銷毀代幣。 - 關閉賬戶:
CloseAccount- 關閉代幣賬戶并轉移剩余SOL。 - 凍結/解凍賬戶:
FreezeAccount,ThawAccount- 凍結或解凍代幣賬戶。 - 同步原生代幣:
SyncNative- 同步包裝的SOL賬戶余額。 - 獲取賬戶數據大小:
GetAccountDataSize- 獲取給定鑄造的賬戶所需大小。 - 初始化不可變所有者:
InitializeImmutableOwner- 為賬戶初始化不可變所有者擴展。 - 金額轉換:
AmountToUiAmount,UiAmountToAmount- 在原始金額和UI顯示金額之間轉換。
當然這么多功能不需全部,我們只需要關注其中的一些有可能為作惡提供條件的功能。
涉及到管理員權限的特殊函數
-
InitializeMint
InitializeMint { /// Number of base 10 digits to the right of the decimal place. decimals: u8, /// The authority/multisignature to mint tokens. mint_authority: Pubkey, /// The freeze authority/multisignature of the mint. freeze_authority: COption<Pubkey>, },參數解釋:
decimals: 代幣的小數位數。mint_authority: 代幣鑄造權限的地址。freeze_authority: 凍結代幣賬戶的地址(可選)。
-
SetAuthority
SetAuthority { /// The type of authority to update. authority_type: AuthorityType, /// The new authority new_authority: COption<Pubkey>, },參數解釋:
authority_type: 指定要更改的權限類型(有 MintTokens, FreezeAccount, AccountOwner, CloseAccount 四類)。new_authority: 新的權限地址。如果設置為None,則表示移除該權限。
SPL 代幣評價維度
由于 SPL 代幣為官方 Program 統一創建,所以在代碼層面不作檢查。
- 權限地址設置,參數設置
freeze_authority是否配置。如果配置凍結特權賬號,則該賬戶可以對用戶的代幣進行凍結。
- 是否行使了特權賬戶的權力
-
FreezeAccount:是否曾經對用戶的代幣賬戶進行凍結。 -
SetAuthority:(MintTokens, FreezeAccount, AccountOwner, CloseAccount) 權限轉移。- Mint Program: MintTokens 權限轉移, FreezeAccount 權限轉移
- Token Account: AccountOwner 權限轉移, CloseAccount 權限轉移
Account 初始化的 CloseAccount 權限賬戶為 None,需要賬戶 owner 先調用
SetAuthority配置權限賬戶后再調用CloseAccount指令。
-
SPL 2022 代幣
SPL 文檔:https://spl.solana.com/token-2022/extensions
SPL 代碼:https://github.com/solana-labs/solana-program-library/tree/master/token/program-2022
Token-2022 中的所有新指令都從 Token 的指令后面開始添加。 Token 有 25 條獨特的指令,索引從 0 到 24。Token-2022 支持所有這些指令,然后在索引 25 處添加了新的功能。
Mint 擴展目前包括:
confidential transfers保密傳輸transfer fees轉讓費closing mint關閉鑄幣廠interest-bearing tokens生息代幣non-transferable tokens不可轉讓代幣permanent delegate永久委托transfer hook轉賬 Hookmetadata pointer元數據指針metadata元數據
Account 擴展目前包括:
memo required on incoming transfers傳入轉賬時需要備注immutable ownership不可變的所有權default account state默認帳戶狀態CPI guardCPI 衛士
SPL 2022 代幣評價維度
在 SPL 代幣的基礎上,添加以下評價維度
-
權限地址設置,參數設置
-
Transfer Fees:Fee 的值是否在合理范圍。 -
Default Account State:初始化的 Account 是否默認凍結狀態。如果初始化的 Account 處于凍結狀態,則無法進行代幣的轉移(出售)。 -
Immutable Owner:用戶的 ATA 代幣賬戶的 owner 不允許轉移。
-
-
是否行使了特權賬戶的權力
-
Interest-Bearing Tokens:是否為生息代幣(createInterestBearingMint),是否調用(updateRateInterestBearingMint)修改過利息參數。 -
Permanent Delegate:權限永久委托情況,被委托的賬戶擁有向任意賬戶鑄造代幣和銷毀任意賬戶代幣的權限。 -
CPI Guard:代幣是否采用了 CPI Guard 功能(createEnableCpiGuardInstruction)來防止非常規的調用,啟用(enableCpiGuard),禁止(disableCpiGuard)
-
-
代碼實現是否存在惡意邏輯
Transfer Hook:重點關注 Hook program 的業務邏輯是否存在作惡的可能。Hook program 由管理員部署與指定,在進行代幣轉移時會調用 Hook program,執行額外的業務邏輯。
案例分析
SPL2022 惡意代幣:https://solscan.io/token/Bz7vBYYuNuK8Y4KRTjaunFFAjzVbAiE1mFM9EGnZ8SHU
從交易的行為來看,這個代幣的作惡手段是在用戶獲得代幣后,利用特權賬戶銷毀用戶的所有代幣。

這就涉及到了 SPL2022的“永久委托”功能,該功能允許委托人“mewfbQ”在任何賬戶中鑄造或銷毀代幣。這是濫用特權的惡意行為。

可以從瀏覽器的信息看到,Permanent Delegate 的賬戶設置為了 mewfbQ 地址,正是通過這個賬戶進行了惡意的操作。


浙公網安備 33010602011771號