script (⏱,💰)

script (⏱,💰)

NG#4 - 合約地址計算

ng4-start

參考安裝入門以完成入門任務。

Vanity Addresses 是 Cairo 的 CTF 獨立任務,類似 Solidity 中的 CREATE2,通過修改 salt 來部署特定前綴後綴的合約地址,再用這個合約去調用目標合約。具體是生成一個開頭是 0x04515 的合約地址,去調用下方的 find_oasis 函數。

 fn find_oasis(ref self: ContractState) {
    let caller = get_caller_address();
    assert(is_oasis(caller), 'NOT_OASIS');
    self.is_oasis_found.write(true);
}

部署 hack 合約#

StarkNet 上全是合約錢包,所以這題可以部署標準的 AA 錢包賬戶,也可以單獨再寫一個合約,不管哪種方式都需要了解 Starknet 的合約是怎麼生成的。我採取的方式是編寫 hack 合約: AA -> hack 合約 -> find_oasis

Cairo 中要實現 A 合約調用 B 合約,需要用 DispatcherTrait,可參考 corelib 裡的 test_contract.cairo。這個 hack 合約比較簡單。

寫完後進行合約部署,我採用 StarkNet Book 中推薦的 starkli,如果不清楚流程,metaschool 裡有詳細教學。大致流程是 scarb build -> starkli declare -> starkli deploy。

需要用 salt=0 去部署 hack.cairo,驗證後面計算是否正確,命令是
starkli deploy [classHash] --salt 0 --network=goerli-1

classhash 是 starkli declare 生成的。

deploy 後出現的文字最後一行就是合約地址。接下來需要用任意語言的 SDK 中計算合約的函數去驗證 salt=0 時地址是否正確,如果正確就寫個迴圈去找目標 salt。

計算滿足條件的合約地址#

StarkNet 中的合約地址是通過 pedersen 計算得出的,具體見StarkNet 官方文檔contract_address := pedersen( “STARKNET_CONTRACT_ADDRESS”, deployer_address, salt, class_hash, constructor_calldata_hash)

在 Cario Star 電報群搜索群裡,發現 2 個 rust 庫可以計算地址:
Option 1: starkli lab https://github.com/xJonathanLEI/starkli/blob/e4d23076b67c05fccc2d7bda069561daaa1fde06/src/subcommands/lab/mine_udc_salt.rs#L37
Option 2: @th0rgal0 's vanity address in their github https://github.com/Th0rgal/vanity-starknet

嘗試後發現 starkli lab 不會用,vanity-starknet 只能生成前綴 0x0000... 的地址,所以得找個 SDK 自己寫。我採用的是 Starknet.js

觀察之前部署合約的 transaction,starkli deploy其實是調用了 UniversalDeployer (UDC) 合約,這個合約統一負責把 classhash 實例化成新合約。參數需要 classHash, salt, calldata,而 calldata _len 和 unique 應該是 starkli 自動處理的。我部署的 Hack 合約沒有構造參數,所以 calldata 是空 array。

UDC

很容易在 starknet.js 的庫裡搜到計算地址的 例子

本地建一個 nodejs 專案,安裝 starknet、jest、typescript 等依賴後,按例子寫了測試,發現 salt=0 的地址對不上。

於是又在庫裡搜其他測試用例,發現當 unique=1 時,計算用的 salt 需要是 hash(deployer, salt),deployerAddress 是 UDC,才和 starkli 能對上。

代碼計算出的地址開頭是 0x593c,而部署的是0x0593c,對比時直接去掉一個 0 就行了。也就是需要對比的是"0x4515"而不是"0x04515"

我在 salt 接近 4 萬的時候計算到了需要的值,沒做任何優化和多線程,用了 10 多分鐘。

更換 salt 後部署的新合約(salt 要轉為 hex 再傳),得到 Hack 合約地址 0x04515bf8e9d0c....

在本地用 starkli invoke調用 hack 方法後完成任務。

更新:得到 starkli 作者的回答後,starkli lab mine-udc-salt能在幾秒內得到結果,具體見 https://github.com/xJonathanLEI/starkli/issues/45#issuecomment-1810015094

總結#

除去入門,這是 CTF 的第一題,不算難,但需要熟悉 StarkNet 相關內容。編寫合約去解題是 CTF 的常規操作,NG 的題目也不例外,所以需要熟悉合約間的調用。另外本題也開始接觸到了 SDK 的使用,部分操作需要鏈下計算。

ng4-summary

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。