Declaring, deploying, and interacting with the HelloStarknet contract locally

If you encounter an issue while following this tutorial, check out "Hello, Starknet!" quickstart tutorial troubleshooting.

Introduction

Welcome to the third installment of the "Hello, Starknet!" quickstart series, the official tutorial for starting your journey as a Starknet developer! 🚀

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:

Predeployed FeeToken
ETH Address: 0x49D36570D4E46F48E99674BD3FCC84644DDD6B96F7C741B1562B82F9E004DC7
STRK Address: 0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d
Class Hash: 0x046ded64ae2dead6448e247234bab192a9c483644395b66f2155f2614e5804b0

Predeployed UDC
Address: 0x41A78E741E5AF2FEC34B695679BC6891742439F7AFB8484ECD7766661AD02BF
Class Hash: 0x7B3E05F48F0C69E4A65CE5E076A66271A527AFF2C34CE1083EC6E1526997A69

Chain ID: SN_SEPOLIA (0x534e5f5345504f4c4941)

...

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, 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:

command: account import
account_name: account-1
add_profile: Profile devnet successfully added to 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 Contract classes and instances.

To declare the HelloStarknet contract, run:

sncast --profile=devnet declare \
    --contract-name=HelloStarknet

If successful, the output of the declaration should resemble the following:

command: declare
class_hash: 0x044701b93b7d2c072d37ebed1f2955f77472146fb0fbac158bd860426f72a9d6
transaction_hash: 0x0687bfb07896505bf44ea65c71d11a847ab33a52cb3abf3322b5107a2f256111
...

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 Compiled class hash.

Deploying HelloStarknet locally

With HelloStarknet declared, you can now deploy an instance of it by running:

sncast --profile=devnet deploy \
    --class-hash=0x044701b93b7d2c072d37ebed1f2955f77472146fb0fbac158bd860426f72a9d6 \
    --salt=0

The --salt option is used to force a consistent address for the deployed contract.

If successful, the result should resemble the following:

command: deploy
contract_address: 0x071865534dda7487b6c7b73d435e1f41d3fd41f6d3c4fcf4448f9770677f820d
transaction_hash: 0x00eb383d6cd4b760369198a3025321084249c4fbdfe1038f774062d4b1d47fed
...

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=0x071865534dda7487b6c7b73d435e1f41d3fd41f6d3c4fcf4448f9770677f820d \
    --function=get_balance

If successful, the result should resemble the following:

command: call
response: [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=0x071865534dda7487b6c7b73d435e1f41d3fd41f6d3c4fcf4448f9770677f820d \
    --function=increase_balance \
    --arguments=42

If successful, the result should resemble the following:

command: invoke
transaction_hash: 0x069679d0cf21851b299ef24fcdae7478cea6e730432365b6eef1f4f280ba68da

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 = 2a16):

command: call
response: [0x2a]