Declaring, deploying, and interacting with the HelloStarknet contract locally

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 Devent 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 fetching them into Starkli. To fetch your local node’s first predeployed account, run:

starkli account fetch \
    0x064b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691 \
    --output=account.json \
    --rpc=http://127.0.0.1:5050

http://127.0.0.1:5050 are the local node’s default host and port (which can be configured on initialization using the --host and --port options).

If successful, the result should resemble the following:

Account contract type identified as: OpenZeppelin
Description: OpenZeppelin account contract v0.8.1 compiled with cairo v2.4.1
Downloaded new account config file: account.json

To finish setting up the account, a corresponding Starkli signer, used by Starkli to sign transactions, is also required. In this tutorial, we will use an encrypted keystores signer. Encrypted keystores are JSON files that follow the Web3 secret storage definition and require a password when created and used, preventing your private key from being stored as plain text on your computer. To create an encrypted keystore signer for your fetched account, run:

starkli signer keystore from-key keystore.json

and enter 0x0000000000000000000000000000000071d7bb07b9a64f6f78ac4c816aff4da9 as its private key, along with a password of your choosing that will be used to encrypt it. If successful, the result should resemble the following:

Created new encrypted keystore file: keystore.json
Public key: 0x039d9e6ce352ad4530a0ef5d5a18fd3303c3606a7fa6ac5b620020ad681cc33b

To avoid specifying the account and keystore files in every subsequent Starkli command, export their paths by running:

export STARKNET_ACCOUNT=$(pwd)/account.json
export STARKNET_KEYSTORE=$(pwd)/keystore.json

Declaring HelloStarknet locally

To declare the HelloStarknet contract, navigate into the hello_starknet directory created in Compiling the HelloStarknet contract, run:

starkli declare \
    target/dev/hello_starknet_HelloStarknet.contract_class.json \
    --rpc=http://127.0.0.1:5050 \

and enter your password. If successful, the output of the declaration should resemble the following:

...

Declaring Cairo 1 class: 0x0785c92bf4aa7a89fb62371802aef2f58e2333d8df7e2aadf938efa83735431c
Compiling Sierra class to CASM with compiler version 2.9.1...
CASM class hash: 0x00a3b109389575a420cd0c5ccbd14e9bf2f5b56d50f6085d08202d15ee2b3222
Contract declaration transaction: 0x0498dd3035e000f91c4f02af54e564a99e87e6a765525d92a4c112b0bc44cfc7
Class hash declared:
0x0785c92bf4aa7a89fb62371802aef2f58e2333d8df7e2aadf938efa83735431c

where Class hash declared is the contract’s class hash, which can then be used to deploy an instance of it.

Class hashes are unique per contract and compiler, and may change if either one changes. 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:

starkli deploy \
    0x0785c92bf4aa7a89fb62371802aef2f58e2333d8df7e2aadf938efa83735431c \
    --rpc=http://127.0.0.1:5050 \
    --salt=0

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

and entering your password. If successful, the result should resemble the following:

Deploying class 0x0785c92bf4aa7a89fb62371802aef2f58e2333d8df7e2aadf938efa83735431c with salt 0x0000000000000000000000000000000000000000000000000000000000000000...
The contract will be deployed at address 0x02ceb6da76e2b2b80f2a23ff2910edf1dcc12e1b9d6a27d1da43d7db943e568c
Contract deployment transaction: 0x068b5b84d03fd725433e93e406abdccc577fb49a7a7fa7c9013493c1d5ad9811
Contract deployed:
0x02ceb6da76e2b2b80f2a23ff2910edf1dcc12e1b9d6a27d1da43d7db943e568c

Interacting with HelloStarknet locally

Now that your instance of HelloStarknet is deployed, you can interact with via its functions. Starkli enables interaction with smart contracts via two primary commands, invoke and call.

The call command 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:

starkli call \
    0x02ceb6da76e2b2b80f2a23ff2910edf1dcc12e1b9d6a27d1da43d7db943e568c \
    get_balance \
    --rpc=http://127.0.0.1:5050

If successful, the result should resemble the following:

[
    "0x0000000000000000000000000000000000000000000000000000000000000000"
]

The invoke command 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:

starkli invoke \
    0x02ceb6da76e2b2b80f2a23ff2910edf1dcc12e1b9d6a27d1da43d7db943e568c \
    increase_balance 42 \
    --rpc=http://127.0.0.1:5050

and entering your password. If successful, the result should resemble the following:

Invoke transaction: 0x05be8823fc9b0c8605374d54f23f38badbd1b8ab4cbb680512cfde3f5662947b

You can verify that the state of your local Starknet instance has indeed changed by calling get_balance again:

starkli call \
    0x02ceb6da76e2b2b80f2a23ff2910edf1dcc12e1b9d6a27d1da43d7db943e568c \
    get_balance \
    --rpc=http://127.0.0.1:5050

If all goes well, the result should resemble the following (4210 = 2a16):

[
    "0x000000000000000000000000000000000000000000000000000000000000002a"
]