Declare Contract
This guide demonstrates how to declare a contract on Starknet using Starknet.go.
Prerequisites
- Go 1.18 or higher
- Starknet.go installed
- A Starknet node URL
- An account with sufficient ETH/STRK for transaction fees
- Compiled contract files (
.sierra.jsonand.casm.json)
Overview
This example demonstrates how to declare a contract on Starknet. It uses a simple Hello Starknet contract, but it can be any smart contract.
Declaring a contract on Starknet is the process of registering the contract class on the network. After declaration, you can deploy instances of that contract class using the class hash.
Important Note: Each contract class can only be declared once on Starknet. If you try to declare a contract class that has already been declared, you will receive an error. This is expected behavior as there can be only one contract class per class hash on the network.
Reference: Starknet Contract Classes
Steps
- Rename the ".env.template" file located at the root of the "examples" folder to ".env"
- Uncomment, and assign your Sepolia testnet endpoint to the
RPC_PROVIDER_URLvariable in the ".env" file - Uncomment, and assign your account address to the
ACCOUNT_ADDRESSvariable in the ".env" file (make sure to have a few ETH in it) - Uncomment, and assign your starknet public key to the
PUBLIC_KEYvariable in the ".env" file - Uncomment, and assign your private key to the
PRIVATE_KEYvariable in the ".env" file - Make sure you are in the "simpleDeclare" directory
- Important: Ensure you have the contract files (
contract.casm.jsonandcontract.sierra.json) in the directory. You need to replace these with your own contract files, otherwise the example will return an error since the included contract has already been declared - Execute
go run main.go
After successful declaration, the transaction hash, status, and the class hash will be returned at the end of the execution.
Code Example
package main
import (
"context"
"fmt"
"math/big"
"strings"
"time"
"github.com/NethermindEth/starknet.go/account"
"github.com/NethermindEth/starknet.go/contracts"
setup "github.com/NethermindEth/starknet.go/examples/internal"
"github.com/NethermindEth/starknet.go/rpc"
"github.com/NethermindEth/starknet.go/utils"
)
const (
sierraContractFilePath = "./contract.sierra.json"
casmContractFilePath = "./contract.casm.json"
)
// This example demonstrates how to declare a contract on Starknet.
func main() {
// Load variables from '.env' file
rpcProviderURL := setup.GetRPCProviderURL()
accountAddress := setup.GetAccountAddress()
accountCairoVersion := setup.GetAccountCairoVersion()
privateKey := setup.GetPrivateKey()
publicKey := setup.GetPublicKey()
// Initialise connection to RPC provider
client, err := rpc.NewProvider(context.Background(), rpcProviderURL)
if err != nil {
panic(fmt.Sprintf("Error dialling the RPC provider: %s", err))
}
// Initialise the account memkeyStore (set public and private keys)
ks := account.NewMemKeystore()
privKeyBI, ok := new(big.Int).SetString(privateKey, 0)
if !ok {
panic("Failed to convert privKey to bigInt")
}
ks.Put(publicKey, privKeyBI)
// Here we are converting the account address to felt
accountAddressInFelt, err := utils.HexToFelt(accountAddress)
if err != nil {
fmt.Println("Failed to transform the account address, did you give the hex address?")
panic(err)
}
// Initialise the account
accnt, err := account.NewAccount(
client,
accountAddressInFelt,
publicKey,
ks,
accountCairoVersion,
)
if err != nil {
panic(err)
}
fmt.Println("Established connection with the client")
// Unmarshalling the casm contract class from a JSON file.
casmClass, err := utils.UnmarshalJSONFileToType[contracts.CasmClass](casmContractFilePath, "")
if err != nil {
panic(err)
}
// Unmarshalling the sierra contract class from a JSON file.
contractClass, err := utils.UnmarshalJSONFileToType[contracts.ContractClass](
sierraContractFilePath,
"",
)
if err != nil {
panic(err)
}
// Building and sending the declare transaction.
resp, err := accnt.BuildAndSendDeclareTxn(
context.Background(),
casmClass,
contractClass,
nil,
)
if err != nil {
if strings.Contains(err.Error(), "is already declared") {
fmt.Println("")
fmt.Println("Error: ooops, this contract class was already declared.")
fmt.Println("You need to: ")
fmt.Println("- create a different Cairo contract,")
fmt.Println("- compile it,")
fmt.Println(
"- paste the new casm and sierra json files in this 'examples/simpleDeclare' folder,",
)
fmt.Println(
"- change the 'casmContractFilePath' and 'sierraContractFilePath' variables to the new files names,",
)
fmt.Println(
"and then, run the example again. You can use Scarb for it: https://docs.swmansion.com/scarb/",
)
return
}
panic(err)
}
fmt.Println("Waiting for the transaction status...")
txReceipt, err := accnt.WaitForTransactionReceipt(context.Background(), resp.Hash, time.Second)
if err != nil {
panic(err)
}
// This returns us with the transaction hash and status
fmt.Printf("Transaction hash response: %v\n", resp.Hash)
fmt.Printf("Transaction execution status: %s\n", txReceipt.ExecutionStatus)
fmt.Printf("Transaction status: %s\n", txReceipt.FinalityStatus)
fmt.Printf("Class hash: %s\n", resp.ClassHash)
}Explanation
Declare Transaction Flow
- Load Environment: Load RPC endpoint and account credentials from environment variables
- Initialize RPC Client: Connect to the Starknet RPC provider
- Setup Account: Initialize account with keystore and credentials
- Unmarshal Contracts: Load both CASM and Sierra contract classes from JSON files
- Build and Send: Use
BuildAndSendDeclareTxnto declare the contract - Wait for Receipt: Wait for the transaction to be confirmed on-chain
- Display Results: Show transaction hash, execution status, and class hash
Contract Files
You need two files to declare a Sierra (Cairo 1+) contract:
- contract.sierra.json: The Sierra representation of your contract
- contract.casm.json: The Cairo Assembly (CASM) compiled version
These files are generated when you compile your Cairo contract using Scarb or the Cairo compiler.
Class Hash
The class hash is a unique identifier for your contract class. After successful declaration:
- Use this class hash to deploy contract instances
- The class hash is deterministically computed from the contract code
- The same contract code will always produce the same class hash
Compiling Contracts
To compile your own Cairo contract and generate the required files, you can use Scarb:
# Install Scarb
curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | sh
# Compile your contract
scarb build
# The compiled files will be in the target/dev directoryBest Practices
- Unique Contracts: Always use a new, undeclared contract for testing declare transactions
- Version Control: Keep track of declared class hashes for deployment
- Fee Estimation: Ensure sufficient funds for declaration fees (can be significant for large contracts)
- Environment Variables: Store sensitive credentials in environment variables
- Error Handling: Handle the "already declared" error gracefully
- Test on Testnet: Always test contract declaration on Sepolia before mainnet
- Contract Verification: Verify your contract files are valid before attempting declaration
Common Issues
Already Declared Error
Error: ooops, this contract class was already declared.Solution: Each contract class can only be declared once. You need to:
- Create a different Cairo contract
- Compile it to generate new
.sierra.jsonand.casm.jsonfiles - Update the file paths in the code
- Run the example again
Invalid Contract Files
Error unmarshalling contract classSolution: Ensure your contract files are:
- Valid JSON format
- Generated from a compatible Cairo compiler version
- Both Sierra and CASM files are from the same contract
Insufficient Funds
Error: insufficient funds for declarationSolution: Ensure your account has enough STRK/ETH to cover:
- Declaration transaction fees
- Gas costs for large contracts can be significant
Invalid Account Configuration
Failed to transform the account addressSolution: Verify your .env file has:
- Valid hex format account address (starting with 0x)
- Correct private and public keys
- Matching key pairs
Related Examples
- Deploy Contract - Learn how to deploy declared contracts
- Deploy with UDC - Deploy using Universal Deployer Contract
- Invoke Contract - Interact with deployed contracts

