NEWTON
Asked
23 days ago
10
views
0
What are steps to create a new contract using starknetjs?
Newton
asked
23 days ago
0
Accepted answer
When you have compiled your new Cairo contract, you can deploy it in the network. In Starknet, a new contract has to be added in two phases :
You must first declare your contract class and only then deploy a new instance of it!
Both declaration and deployment will cost fees. That's why these functions are methods of the Account object. The account shall be enough funded to be able to process.
You will have only one Class Hash for a contract code, but you can have as many contract instances as you need. Other users of the network can use your declared contract. It means that if somebody has already declared a contract class (and paid this declaration), and if you would like to have your own instance of this contract, you have only to deploy (and pay) a new instance. Example : if you want an ERC20 contract, and somebody has already declared an ERC20 contract conform to your needs, you have just to deploy a new instance of this contract class.
import { Provider, Account, Contract, ec, json, stark, uint256, shortString } from "starknet";
TLDR: Starknet.js is not able to calculate a Class Hash 😮.The Class Hash should be a result of the compilation, but today, it's not recorded in the compiled file. It could be calculated during the declaration activity, but it's actually too long to process. So you need to calculate the Class hash and add it as a constant in your code.
You can calculate it with some other tool, for example, Starkli
Starknet.js proposes a function to perform both operations in one step: declareDeploy()
.Here, to declare & deploy a Test.cairo smart contract, in Testnet 1 :
// connect provider const provider = new Provider({ sequencer: { network: "goerli-alpha" } }); // connect your account. To adapt to your own account : const privateKey0 = process.env.OZ_ACCOUNT_PRIVATE_KEY; const account0Address: string = "0x123....789"; const starkKeyPair0 = ec.getKeyPair(privateKey0); const account0 = new Account(provider, account0Address, starkKeyPair0); // Declare & deploy the Test contract in devnet // ClassHash has been calculated previously with specific tool const testClassHash = "0xff0378becffa6ad51c67ac968948dbbd110b8a8550397cf17866afebc6c17d"; const compiledTest = json.parse(fs.readFileSync("./compiled_contracts/test.json").toString("ascii")); const deployResponse = await account0.declareDeploy({ contract: compiledTest, classHash: testClassHash }); // Connect the new contract instance : const myTestContract = new Contract(compiledTest.abi, deployResponse.deploy.contract_address, provider); console.log('✅ Test Contract connected at =', myTestContract.address);
If the contract class is already deployed, it's faster and cheaper to use deployContract()
.
// connect provider const provider = new Provider({ sequencer: { network: "goerli-alpha" } }); // connect your account. To adapt to your own account : const privateKey0 = process.env.OZ_ACCOUNT_PRIVATE_KEY; const account0Address: string = "0x123....789"; const starkKeyPair0 = ec.getKeyPair(privateKey0); const account0 = new Account(provider, account0Address, starkKeyPair0); // Deploy Test contract in devnet // ClassHash has been calculated previously with specific tool const testClassHash = "0xff0378becffa6ad51c67ac968948dbbd110b8a8550397cf17866afebc6c17d"; const deployResponse = await account0.deployContract({ classHash: testClassHash }); // read abi of Test contract const { abi: testAbi } = await provider.getClassAt(deployResponse.contract_address); if (testAbi === undefined) { throw new Error("no abi.") }; // Connect the new contract instance : const myTestContract = new Contract(testAbi, deployResponse.contract_address, provider); console.log('✅ Test Contract connected at =', myTestContract.address);
If you want only declare a new Contract Class, use declare()
.
// connect provider const provider = new Provider({ sequencer: { network: "goerli-alpha" } }); // connect your account. To adapt to your own account : const privateKey0 = process.env.OZ_ACCOUNT_PRIVATE_KEY; const account0Address: string = "0x123....789"; const starkKeyPair0 = ec.getKeyPair(privateKey0); const account0 = new Account(provider, account0Address, starkKeyPair0); // Declare Test contract in devnet // ClassHash has been calculated previously with specific tool const testClassHash = "0xff0378becffa6ad51c67ac968948dbbd110b8a8550397cf17866afebc6c17d"; const compiledTest = json.parse(fs.readFileSync("./compiled_contracts/test.json").toString("ascii")); const declareResponse = await account0.declare({ contract: compiledTest, classHash: testClassHash }); await provider.waitForTransaction(declareResponse.transaction_hash); console.log('✅ Test Contract Class Hash =', declareResponse.class_hash);
You can use the declare() function for an already declared contract; it will not generate any error.
Newton
answered
23 days ago
How do I create account using starknetjs?
How do I create AX (ArgentX) contract using starknetjs?
How do I create OZ (Open Zeppelin) contract using starknetjs?
How do I create my own account abstraction using starknetjs?
How can I connect to deployed StarkNet contract using starknetjs?
How can I interact with my contract on Starknet using starknetjs?
Did you change the factory/create2 part (to compute pool addresses)? What's easier, adapt the create2 trick in Solidity then transpile or transpile first then adapt in Cairo?
Does Cairo work in python3.10 venv? I can’t install python 3.9
Which oracle service provider is StarkNet using?
Is there any way to abi-encode calldata to pass to `account.execute`?
why does keccak256 replace sha256 in warp?
Is there a way to find events in a block without getting receipt for all transactions on Starknet?
ApeWorX: Why am I getting an "account __execute__" error message?
Warp Traspiler error: the warp-related package was not found. How do I generate python packages?