次のテキストを日本語に翻訳してください:
没有完成入门任务的参考安装入门
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。
很容易在 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 的使用,部分操作需要链下计算。