NEWTON
Asked
3 months ago
11
views
0
What are steps to create a new contract using starknetjs?
Newton
asked
3 months 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
3 months 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?
Can I transpile any solidity version?
How can I interact with my contract on Starknet using starknetjs?
What do I have as the result of a Cairo contract in JavaScript?
Are there situations in which we prefer declaring variables as `local` vs `tempvar`?
Do I need to learn cairo to develop on starknet?
How to use Kakarot for my Solidity Contracts?
When you run warp deploy or warp invoke, which account is paying for the tx fees on the Goerli testnet?