Live Software Developer Ltd Logo
HomeServicesWeb HostingDomainsEmail HostingArticlesContact UsAbout Us

Smart Contract Development With Starknet & Cairo Language with Katana Local Node

Smart Contract Development With Starknet & Cairo Language with Katana Local Node

Created On:
Sun Aug 13 2023 (5:16:10 PM)
Updated On:
Fri Sep 08 2023 (6:48:35 PM)
Starknet is a layer 2 chain to Ethereum which provides the power of zk-STARKs technology for scalability, privacy, and security. This article is going to articulate the steps to creating your own smart contract that leverages the power of Cairo language with Starknet to make a wonderful product.

Learn to build & deploy Starknet contract in one go!

Guide to developing Contracts on chain with Cairo.

Katana

Prerequisites

  1. Linux like environment - Debian system or WSL on windows
  2. Rust - Setup - Required (Better to have it)
  3. Cairo - Setup - Language to be used in writing the smart contract(s)
  4. Scarb - Setup - Cairo package manager like Cargo for Rust
  5. Katana - Setup - Local Development Node
  6. Starkli - Setup - CLI tool to help in deploying the contract and to interact with it.
  7. Starknet Foundry - setup - For easy smart contract development

Resources

  1. Cairo book - Read
  2. Starknet book - Read
  3. Starknet Foundry - Read

This will guide you throught the local development and deployment of Starknet contracts.

If you are on windows you need to set up wsl.

To view wsl files on windows, type \\wsl$ on Windows File Explorer bar

How to create accounts (katana)

Once Katana is installed start the local starknet node;

katana --accounts 3 --seed 0 --gas-price 250

It will start a local starknet node with 3 deployed accounts;

$ katana --accounts 3 --seed 0 --gas-price 250



██╗  ██╗ █████╗ ████████╗ █████╗ ███╗   ██╗ █████╗ 
██║ ██╔╝██╔══██╗╚══██╔══╝██╔══██╗████╗  ██║██╔══██╗
█████╔╝ ███████║   ██║   ███████║██╔██╗ ██║███████║
██╔═██╗ ██╔══██║   ██║   ██╔══██║██║╚██╗██║██╔══██║
██║  ██╗██║  ██║   ██║   ██║  ██║██║ ╚████║██║  ██║
╚═╝  ╚═╝╚═╝  ╚═╝   ╚═╝   ╚═╝  ╚═╝╚═╝  ╚═══╝╚═╝  ╚═╝
                                                      

        
PREFUNDED ACCOUNTS
==================

| Account address |  0x3ee9e18edc71a6df30ac3aca2e0b02a198fbce19b7480a63a0d71cbd76652e0 
| Private key     |  0x300001800000000300000180000000000030000000000003006001800006600
| Public key      |  0x1b7b37a580d91bc3ad4f9933ed61f3a395e0e51c9dd5553323b8ca3942bb44e

| Account address |  0x33c627a3e5213790e246a917770ce23d7e562baa5b4d2917c23b1be6d91961c 
| Private key     |  0x333803103001800039980190300d206608b0070db0012135bd1fb5f6282170b
| Public key      |  0x4486e2308ef3513531042acb8ead377b887af16bd4cdd8149812dfef1ba924d

| Account address |  0x1d98d835e43b032254ffbef0f150c5606fa9c5c9310b1fae370ab956a7919f5 
| Private key     |  0x7ca856005bee0329def368d34a6711b2d95b09ef9740ebf2c7c7e3b16c1ca9c
| Public key      |  0x7006c42b1cfc8bd45710646a0bb3534b182e83c313c7bc88ecf33b53ba4bcbc
    

ACCOUNTS SEED
=============
0

We will use these 3 accounts to deploy and interact with the smart contract.

This will also provide the JSON-RPC server to use for local dev as:

http://0.0.0.0:5050

Important! Don't stop the created server by Katana. Everything relies on it.

Start a new terminal shell to continue with the other commands.

Preparing Accounts for Smart Contract Deployment

We will create a signer and an account descriptor for one of the 3 wallets.

Creating a Keystore from account 1's private key

Use the commands below:

mkdir ~/.starkli-wallets/deployer -p

Then;

starkli signer keystore from-key ~/.starkli-wallets/deployer/account1_keystore.json

Result

Created new encrypted keystore file: /home/dalmas/.starkli-wallets/deployer/account1_keystore.json
Public key: 0x04486e2308ef3513531042acb8ead377b887af16bd4cdd8149812dfef1ba924d

To Preview

cat ~/.starkli-wallets/deployer/account1_keystore.json

Result:

{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"1e4c13c7e7a5ad5f24d49ab08a0dde59"},"ciphertext":"0b09cca82505487f6a992a76b13fcdced3b982315a832306579ce4a79a4cc70e","kdf":"scrypt","kdfparams":{"dklen":32,"n":8192,"p":1,"r":8,"salt":"65eef381e21f488e8889b3000cf659e0a2ea5e9fa79ef3ec93909d5b0d48b7c7"},"mac":"5aa2a6ae31ae46f73d142617826172564d280914b466769343e901b3fe98ae58"},"id":"e5159eee-4346-4b31-93ae-acdd018cd5ce","version":3}

The Private Key we added can be found in the Katana JSON-RPC server started at stage one; You can pick any wallet (we've used the first one)

Creating an Account Descriptor;

The account descriptor is a json file, and you can get the public key and wallet address above;

  1. Create a file that will hold the signer
touch ~/.starkli-wallets/deployer/account1_account.json
  1. Edit the file and paste in the json object into it.
nano ~/.starkli-wallets/deployer/account1_account.json

Paste this into the file.

{
  "version": 1,
  "variant": {
        "type": "open_zeppelin",
        "version": 1,
        "public_key": "<ACCOUNT_PUBLIC_KEY>"
  },
    "deployment": {
        "status": "deployed",
        "class_hash": "<SMART_WALLET_CLASS_HASH>",
        "address": "<ACCOUNT_ADDRESS>"
  }
}

Update the <ACCOUNT_PUBLIC_KEY> with the public key of the account you chose from Katana

Update the <ACCOUNT_ADDRESS> with the address of the account you chose from Katana

Update the <SMART_WALLET_CLASS_HASH> with the hash generated by running the command below

starkli class-hash-at <ACCOUNT_ADDRESS> --rpc http://0.0.0.0:5050

Result

0x04d07e40e93398ed3c76981e72dd1fd22557a78ce36c0515f679e27f0bb5bc5f

Notice how we've used Katana's RPC End Point http://0.0.0.0:5050.

We've generated the class hash, so now we will replace <SMART_WALLET_CLASS_HASH> with it.

Finally, to view the contents of the file use

cat ~/.starkli-wallets/deployer/account1_account.json

Result:

{
  "version": 1,
  "variant": {
        "type": "open_zeppelin",
        "version": 1,
        "public_key": "0x4486e2308ef3513531042acb8ead377b887af16bd4cdd8149812dfef1ba924d"
  },
    "deployment": {
        "status": "deployed",
        "class_hash": "0x04d07e40e93398ed3c76981e72dd1fd22557a78ce36c0515f679e27f0bb5bc5f",
        "address": "0x33c627a3e5213790e246a917770ce23d7e562baa5b4d2917c23b1be6d91961c"
  }
}

To inspect the public key;

starkli signer keystore inspect ~/.starkli-wallets/deployer/account1_keystore.json

You will be asked to enter password then the result will be as below.

Result:

Public key: 0x04486e2308ef3513531042acb8ead377b887af16bd4cdd8149812dfef1ba924d

Navigate to ubuntu/root/.starkli-wallets/deployer to see your accounts.

ls ~/.starkli-wallets/deployer

Result:

account0_account.json   account1_keystore.json  account.json
account0_keystore.json  account3_account.json   keystore.json
account1_account.json   account3_keystore.json

You might notice more than one account, stick to account1_account.json & account1_keystore.json

Export(Add as Environment variables) account location and keystore location

After doing the above, you need to export your account and keystore to set them as environment variables to avoid writing loong paths to your smart wallet account and keystore

export STARKNET_ACCOUNT=~/.starkli-wallets/deployer/account1_account.json
export STARKNET_KEYSTORE=~/.starkli-wallets/deployer/account1_keystore.json

Deploying to local development Node [Katana]

This section will show you on how to deploy your first smart contract to the local dev node[Katana]

We will be using an example from Foundry that gives us the HelloStarknet Contract

Clone the online repo for a smart contract by following the docs here or use the git command below.

git clone https://github.com/foundry-rs/starknet_forge_template.git

After cloning the example contract, navigate to starknet_forge_template

cd starknet_forge_template/

Then, Build the project by running

scarb build

Once you have ran the above command, you will notice you have your target folder

Start starkli [If it is not auto started]

To confirm whether its up run:

starkli --version

If starkli command not found, try the command below:

. /home/dalmas/.starkli/env

Declare your contract

With declaring the smark contract, we are preparing it for deployment. Use the command below:

starkli declare target/dev/starknet_forge_template_HelloStarknet.sierra.json --compiler-version=2.1.0 --account $STARKNET_ACCOUNT --keystore $STARKNET_KEYSTORE --rpc http://0.0.0.0:5050

After declaring, you will get the following output

Enter keystore password: 

Declaring Cairo 1 class: 0x04970172fe2dfe1208dd07a52d0cea1663b481211c0963052c43e185c35ec4ee

Compiling Sierra class to CASM with compiler version 2.0.1...

CASM class hash: 0x03eb55a3f9f7485408838b08067c3b0f5d72523c525f568b04627464f5464749

Contract declaration transaction: 0x03b747b5448c7259764491a5242a92e1926b6865fe6bad4b6a357583d7a27c0d

Class hash declared:
0x04970172fe2dfe1208dd07a52d0cea1663b481211c0963052c43e185c35ec4ee

Take Note of the Class hash declared

Deploy the contract

Deploy the declared contract to the local node.

starkli deploy <DECLARE_CLASS_HASH> --account $STARKNET_ACCOUNT --keystore $STARKNET_KEYSTORE --rpc http://0.0.0.0:5050

You might notice the above command does not have --compiler-version=2.1.0 because we are deploying to the local node(Katana) and not an online node like goerli

Example

starkli deploy 0x04970172fe2dfe1208dd07a52d0cea1663b481211c0963052c43e185c35ec4ee --account $STARKNET_ACCOUNT --keystore $STARKNET_KEYSTORE --rpc http://0.0.0.0:5050

Successful Result

Enter keystore password: 

Deploying class 0x04970172fe2dfe1208dd07a52d0cea1663b481211c0963052c43e185c35ec4ee with salt 0x02006f8d9865b5b4e83c579023c7366658918f354ffcc11bd0e81cb9ec1991b9...

The contract will be deployed at address 0x01b364a76a9656ec1c06cd4dc3a915cc086577e8e2e56d886569eab5f381873d

Contract deployment transaction: 0x043f366e5bdf04e50546382f2184b9e90d79ccb98cbe998d54e33048c9df9288

Contract deployed:
0x01b364a76a9656ec1c06cd4dc3a915cc086577e8e2e56d886569eab5f381873d

N/B: The success result might be different from what you get. Don't clear the output from terminal or save the output before clearing your terminal.

The deployed contract, has two methods:

increase_balance // Writing/Setting method
get_balance // Reading/Getting method

How to make contract view call

starkli call <CONTRACT_ADDRESS> <METHOD> --rpc http://0.0.0.0:5050

<CONTRACT_ADDRESS> is the address that is in the deployment result under The contract will be deployed at address

<METHOD> is one of the methods in the written contract that is HelloStarknet Contract.

Example
starkli call 0x01b364a76a9656ec1c06cd4dc3a915cc086577e8e2e56d886569eab5f381873d get_balance --rpc http://0.0.0.0:5050

Result:

[
    "0x0000000000000000000000000000000000000000000000000000000000000000"
]

Writing to the contract

To edit the contract state, you use the command below:

starkli invoke <CONTRACT_ADDRESS> <METHOD> [ARGS] --rpc http://0.0.0.0:5050 --account <PATH_TO_SMART_WALLET_ACCOUNT_JSON> --keystore <PATH_TO_SMART_WALLET_KEYSTORE_FOR_A_GIVEN_ACCOUNT>
Example
starkli invoke 0x01b364a76a9656ec1c06cd4dc3a915cc086577e8e2e56d886569eab5f381873d increase_balance 2 --rpc http://0.0.0.0:5050 --account $STARKNET_ACCOUNT --keystore $STARKNET_KEYSTORE

Result:

Invoke transaction: 0x030c3aab451718e29ddcd61119e1cb11d9241360bb4c23c104a209c226755ee9

Get Transaction Status/Information

Call the command below to get transaction information:'

starkli transaction-receipt <TRANSACTION_ID> --rpc http://0.0.0.0:5050
Example
starkli transaction-receipt 0x030c3aab451718e29ddcd61119e1cb11d9241360bb4c23c104a209c226755ee9 --rpc http://0.0.0.0:5050

Result

{
  "type": "INVOKE",
  "transaction_hash": "0x30c3aab451718e29ddcd61119e1cb11d9241360bb4c23c104a209c226755ee9",
  "actual_fee": "0x24a4dc",
  "status": "ACCEPTED_ON_L2",
  "block_hash": "0x2c728cc838be1894f3e3cab93aa3a0401ea9a50f022eb0a2f07bf9bdf732b5a",
  "block_number": 3,
  "messages_sent": [],
  "events": [
    {
      "from_address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
      "keys": [
        "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9"
      ],
      "data": [
        "0x1d98d835e43b032254ffbef0f150c5606fa9c5c9310b1fae370ab956a7919f5",
        "0x69420",
        "0x24a4dc",
        "0x0"
      ]
    }
  ]
}

Katana keeps the JSON-RPC Node

Listening to all the incoming calls and recording/showing the transactions Katana

Made with ❤️

Dalmas Ogembo - CEO Live Software Developer Ltd, Fullstack Software Developer - Portifolio | Github | Twitter | LinkedIn | Telegram

Cynthia Kamau - Github | Twitter | LinkedIn | Telegram

Felix Awere - Portfolio | GitHub | Twitter | LinkedIn | telegram

Ochieng Odhiambo - Twitter | LinkedIn

Web3Clubs