The following text is in English:
Reference for incomplete beginner tasks Installation Guide
Vanity Addresses is a standalone CTF task in Cairo, similar to CREATE2 in Solidity. It deploys contract addresses with specific prefixes and suffixes by modifying the salt, and then uses this contract to call the target contract. Specifically, it generates a contract address with the prefix 0x04515 and calls the find_oasis function below.
fn find_oasis(ref self: ContractState) {
let caller = get_caller_address();
assert(is_oasis(caller), 'NOT_OASIS');
self.is_oasis_found.write(true);
}
Deploy the hack contract#
Since StarkNet is full of contract wallets, you can deploy a standard AA wallet account for this question, or you can write a separate contract. Either way, you need to understand how Starknet contracts are generated. I chose to write the hack contract: AA -> hack contract -> find_oasis.
In Cairo, to implement A contract calling B contract, you need to use the DispatcherTrait, which can be referred to in the corelib's test_contract.cairo. This hack contract is relatively simple.
After writing it, deploy the contract. I used starkli, which is recommended in the StarkNet Book. If you are not familiar with the process, there is a detailed tutorial in metaschool. The general process is scarb build -> starkli declare -> starkli deploy.
Use salt=0 to deploy hack.cairo and verify if the subsequent calculation is correct. The command is starkli deploy [classHash] --salt 0 --network=goerli-1
.
classhash is generated by starkli declare.
The last line of the text that appears after deployment is the contract address. Next, you need to use a function in an SDK in any language to calculate the contract and verify if the address is correct when salt=0. If it is correct, write a loop to find the target salt.
Calculate the contract address that meets the conditions#
The contract address in StarkNet is calculated using pedersen, as described in the StarkNet official documentation: contract_address := pedersen( “STARKNET_CONTRACT_ADDRESS”, deployer_address, salt, class_hash, constructor_calldata_hash)
In the Cairo Star Telegram group, I found two Rust libraries that can calculate the address:
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
After trying, I found that starkli lab is not usable, and vanity-starknet can only generate addresses with the prefix 0x0000.... So I need to write my own code using an SDK. I used Starknet.js.
By observing the transaction of the previously deployed contract, starkli deploy
actually calls the UniversalDeployer (UDC) contract, which is responsible for instantiating the classhash into a new contract. The parameters required are classHash, salt, calldata, and calldata _len and unique should be automatically handled by starkli. The hack contract I deployed has no constructor parameters, so calldata is an empty array.
It is easy to find an example of calculating the address in the starknet.js library here.
Create a new Node.js project locally, install dependencies such as starknet, jest, typescript, etc., and write a test based on the example. However, I found that the address calculated with salt=0 does not match.
So I searched for other test cases in the library and found that when unique=1, the salt used for calculation needs to be hash(deployer, salt), where deployerAddress is the UDC, in order to match starkli.
The calculated address starts with 0x593c
, while the deployed address is 0x0593c
. To compare, simply remove one 0. Therefore, what needs to be compared is "0x4515"
instead of "0x04515"
.
I calculated the required value when the salt was close to 40,000, without any optimization or multithreading, and it took more than 10 minutes.
After changing the salt, deploy the new contract (the salt needs to be converted to hex before passing it), and obtain the Hack contract address 0x04515bf8e9d0c....
Use starkli invoke
to call the hack method locally and complete the task.
Update: After receiving a response from the author of starkli,
starkli lab mine-udc-salt
can obtain results within a few seconds. See https://github.com/xJonathanLEI/starkli/issues/45#issuecomment-1810015094 for details.
Summary#
Apart from the beginner tasks, this is the first question in the CTF, which is not difficult but requires familiarity with StarkNet-related content. Writing contracts to solve problems is a common operation in CTF, and NG's questions are no exception, so it is necessary to be familiar with contract calls. In addition, this question also introduces the use of SDKs, and some operations require off-chain calculations.