If you encounter an issue while following this tutorial, see Troubleshooting.

Introduction

Welcome to the third installment of the Deploy your first contract guide! 🥇 Local networks, also known as development networks or devnets, enable a fast and private development process, making them ideal for taking your first Starknet steps. This installment of the series will therefore guide you through the steps necessary to declare, deploy, and interact with the HelloStarknet contract on your very own local instance of Starknet.

Initializing a local Starknet instance

A local Starknet instance can be easily initialized using Starknet Devnet by simply running:
starknet-devnet --seed=0
The --seed option is used to force consistent addresses of predeployed account (see more details below).
If successful, the result should resemble the following:
Chain ID: SN_SEPOLIA (0x534e5f5345504f4c4941)

Predeployed FeeToken
ETH Address: 0x49D36570D4E46F48E99674BD3FCC84644DDD6B96F7C741B1562B82F9E004DC7
Class Hash: 0x9524A94B41C4440A16FD96D7C1EF6AD6F44C1C013E96662734502CD4EE9B1F
STRK Address: 0x4718F5A0FC34CC1AF16A1CDEE98FFB20C31F5CD61D6AB07201858F4287C938D
Class Hash: 0x76791EF97C042F81FBF352AD95F39A22554EE8D7927B2CE3C681F3418B5206A

Predeployed UDC
Address: 0x41A78E741E5AF2FEC34B695679BC6891742439F7AFB8484ECD7766661AD02BF
Class Hash: 0x7B3E05F48F0C69E4A65CE5E076A66271A527AFF2C34CE1083EC6E1526997A69

...
Starknet Devnet should keep running for the following sections to work.

Fetching a predeployed account

To learn more about Starknet accounts, check out the Accounts section.
To interact with your local Starknet instance, you first need an account. Luckily, the result of initializing a local Starknet instance using Starknet Devnet should also include a list of predeployed accounts that resembles the following:
| Account address |  0x064b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691
| Private key     |  0x0000000000000000000000000000000071d7bb07b9a64f6f78ac4c816aff4da9
| Public key      |  0x039d9e6ce352ad4530a0ef5d5a18fd3303c3606a7fa6ac5b620020ad681cc33b

| Account address |  0x078662e7352d062084b0010068b99288486c2d8b914f6e2a55ce945f8792c8b1
| Private key     |  0x000000000000000000000000000000000e1406455b7d66b1690803be066cbe5e
| Public key      |  0x007a1bb2744a7dd29bffd44341dbd78008adb4bc11733601e7eddff322ada9cb

...
This allows to avoid creating and deploying new accounts, and instead simply importing them to Starknet Foundry. To import your local node’s first predeployed account, use a new terminal window to navigate into the hello_starknet directory created in Generating HelloStarknet and run:
sncast account import \
    --address=0x064b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691 \
    --type=oz \
    --url=http://127.0.0.1:5050 \
    --private-key=0x0000000000000000000000000000000071d7bb07b9a64f6f78ac4c816aff4da9 \
    --add-profile=devnet \
    --silent
To learn more about sncast account import, see the Starknet Foundry documentation.
If successful, the result should resemble the following:
Success: Account imported successfully

Account Name: account-1
Add Profile:  Profile devnet successfully added to /app/snfoundry.toml

Declaring HelloStarknet locally

Before a contract can be deployed on Starknet, its compiled code needs to be submitted to the network (also known as declaring it).
To learn more about distinction between deploying a contract and declaring it, see the Cairo Book.
To declare the HelloStarknet contract, run:
sncast --profile=devnet declare \
    --contract-name=HelloStarknet
If successful, the result should resemble the following:
Success: Declaration completed

Class Hash:       0x51e0d3b26fb79035afdc64d2214eb18291629b4f2ef132e79c3f3fbe1ba57c4
Transaction Hash: 0x76e28641d96ee0788f5a960931ee717c5dae36f95f227c02d5578a6898d8af3
where class_hash is the contract’s class hash, which can then be used to deploy an instance of it.
To learn more about the class hashes, check out the Cairo Book.

Deploying HelloStarknet locally

With HelloStarknet declared, you can now deploy an instance of it by running:
sncast --profile=devnet deploy \
    --class-hash=0x051e0d3b26fb79035afdc64d2214eb18291629b4f2ef132e79c3f3fbe1ba57c4 \
    --salt=0
The --salt option is used to force a consistent address for the deployed contract.
If successful, the result should resemble the following:
Success: Deployment completed

Contract Address: 0x04035c4db7822523478996bfc2b80d925e671279bb99ed1fb4e4fcc222e344e6
Transaction Hash: 0x04d11358b809c7b8a5aae1a1cf0e72e0b436fb2d0a2dd1a26d009fec7aa74280

Interacting with HelloStarknet locally

Now that your instance of HelloStarknet is deployed, you can interact with via its functions by either calling or invoking them. Calling is used for read functions that don’t modify their contract’s storage, and allows querying a smart contract function without sending a transaction. For example, you can call HelloStarknet’s get_balance function by running:
sncast --profile=devnet call \
    --contract-address=0x04035c4db7822523478996bfc2b80d925e671279bb99ed1fb4e4fcc222e344e6 \
    --function=get_balance
If successful, the result should resemble the following:
Success: Call completed

Response:     0x0
Response Raw: [0x0]
Invoking is used for write functions that modify their contract’s storage, and submits a transaction to the network that changes its state. For example, you can invoke HelloStarknet’s increase_balance function by running:
sncast --profile=devnet invoke \
    --contract-address=0x04035c4db7822523478996bfc2b80d925e671279bb99ed1fb4e4fcc222e344e6 \
    --function=increase_balance \
    --arguments=42
If successful, the result should resemble the following:
Success: Invoke completed

Transaction Hash: 0x02691af0fb2b720b27ae17c844d72244b8fc35f3a3d57b6549736d9a88f8f014
You can verify that your deployed contract’s storage — and by extension, the state of your local Starknet instance — has indeed changed by calling get_balance again. If all goes well, the result should resemble the following (4210=2a1642_{10} = 2a_{16}):
Success: Call completed

Response:     0x2a
Response Raw: [0x2a]