参考入門ガイドを完了していない場合は、こちらを参照してください。
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 で生成されたものです。
デプロイ後に表示されるテキストの最後の行が契約アドレスです。次に、任意の言語の SDK を使用して契約のアドレスを計算し、salt=0 の場合に正しいかどうかを検証する必要があります。正しい場合は、目標の salt を見つけるためにループを作成します。
条件を満たす契約アドレスの計算#
StarkNet の契約アドレスは、ペダーセン計算によって得られます。詳細については、StarkNet 公式ドキュメントを参照してください:contract_address := pedersen( “STARKNET_CONTRACT_ADDRESS”, deployer_address, salt, class_hash, constructor_calldata_hash)
Cairo Star の Telegram グループで検索したところ、2 つの Rust ライブラリがアドレスを計算することがわかりました:
オプション 1:starkli lab https://github.com/xJonathanLEI/starkli/blob/e4d23076b67c05fccc2d7bda069561daaa1fde06/src/subcommands/lab/mine_udc_salt.rs#L37
オプション 2:@th0rgal0 の GitHub の vanity address https://github.com/Th0rgal/vanity-starknet
試してみた結果、starkli lab は使用方法がわからず、vanity-starknet は接頭辞 0x0000... のアドレスしか生成できないことがわかりました。したがって、自分で SDK を書く必要があります。私はStarknet.jsを使用しました。
以前にデプロイした契約のトランザクションを観察すると、starkli deploy
は実際には UniversalDeployer (UDC) 契約を呼び出しています。この契約は、classhash を新しい契約にインスタンス化するための統一的な役割を果たします。パラメータには classHash、salt、calldata が必要で、calldata _len と unique は starkli が自動的に処理するものです。私がデプロイした Hack 契約にはコンストラクタパラメータがないため、calldata は空の配列です。
starknet.js ライブラリのテストケースを見つけることができました。例を参照してください。
ローカルで Node.js プロジェクトを作成し、starknet、jest、typescript などの依存関係をインストールした後、テストを作成しましたが、salt=0 のアドレスが一致しませんでした。
ライブラリ内の他のテストケースを検索したところ、unique=1 の場合、計算に使用する salt は **hash (deployer, salt)** である必要があることがわかりました。deployerAddress は UDC です。これにより、starkli と一致します。
コードで計算されたアドレスの先頭は 0x593c
であり、デプロイされたものは 0x0593c
です。比較する際には、0 を 1 つ削除するだけです。つまり、比較するのは "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 の使用にも触れました。一部の操作はオフチェーンで行う必要があります。