Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Declaring a smart contract" refactor #1416

Merged
merged 7 commits into from
Nov 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,161 +1,162 @@
= Declaring a smart contract

== Overview

Before a contract is deployed on Starknet it first needs to be _declared_. Declaration is the process of submitting a contract's code to Starknet and making it available for future deployments, analogous to registering its blueprint.

This page will guide you through the steps necessary to declare a smart contract on Starknet. For more details on declaration and its benefits, see xref:architecture-and-concepts:smart-contracts/contract-classes.adoc[Contract classes and instances].

== Prerequisites

=== Ensure Starkli and Scarb are installed correctly
Ensure that the below commands are working properly on your system.
Ensure that the following commands are working properly on your system:

[source, bash]
----
starkli --version
scarb --version
snforge --version
sncast --version
asdf --version
----

If either of the above commands fails, see xref:environment-setup.adoc[Setting up your environment].

== Introduction

Deploying a smart contract in Starknet requires two steps:

* Declaring the class of your contract, i.e. sending your contract's code to the network.
* Deploying a contract, i.e. creating an instance of the code you previously declared.

[TIP]
====
If you require a smart contract for testing, you can use this sample contract, link:https://github.com/starknet-edu/starknetbook/blob/main/examples/vote-contracts/src/lib.cairo[`lib.cairo`], from the Starknet Book.
====

== Compiling a smart contract

You can compile a smart contract using the Scarb compiler.

To compile a smart contract, create a directory containing a `Scarb.toml` file and a subdirectory named `src` containing your contract source code.
Before a smart contract can be declared, it first needs to be compiled. To compile an existing smart contract project, simply navigate into the project's directory and run:

Add the following code to the `Scarb.toml` file:

[source,toml]
[source,bash]
----
scarb build
----
[package]
name = "contracts"
version = "0.1.0"

[dependencies]
starknet = ">=2.2.0"
The compiled contract should be saved in the `target/dev/` directory.

[[target.starknet-contract]]
sierra = true
----
If you require a new smart contract project, run either:

Navigate into the newly created directory:
[source,bash]
----
cd <dir_name>
scarb init
----

Run the following command:
in an empty folder or:

[source,bash]
----
scarb build
scarb new <PROJECT_NAME>
----

The compiled contract will be saved in the `target/dev/` directory.
anywhere, and select the default Starknet Foundry as a test runner.

The contract is now compiled and ready to be deployed. Next you will need to declare an RPC provider within your contract.

== Setting an RPC provider
[NOTE]
====
Building a Starknet Foundry project with Scarb requires https://www.rust-lang.org/[Rust] to be installed. You can verify that Rust is installed by running:

To interact with the Starknet network, you need to set an RPC endpoint within Starkli.
rustc --version

The following are the RPC providers available for Starknet:
or install Rust by following the instructions in the https://doc.rust-lang.org/beta/book/ch01-01-installation.html[Rust documentation].

[cols="1,2"]
|===
|Provider name |Description
Moreover, the first time a project is built, some components of Scarb are compiled locally with the Rust toolchain. This process may take a few minutes, but will not happen in subsequent builds.
====

|Infura or Alchemy
|Use a provider like Infura or Alchemy.
In any case, the `Scarb.toml` file in the project's directory should resemble the following (up to versions number):

|Custom configuration
|Set up your own node and use the RPC provider of your node. More information on this can be found within the link:https://book.starknet.io/chapter_4/node.html[Starknet Book].
[source,toml]
----
[package]
name = <PROJECT_NAME>
version = "0.1.0"
edition = "2023_11"

|===
[dependencies]
starknet = "2.8.4"

For demonstration purposes, the Starknet Sequencer's Gateway is used in the below steps.
[dev-dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.32.0" }
assert_macros = "2.8.4"

== Declaring a smart contract
[[target.starknet-contract]]
sierra = true
----

A contract can be declared on Starknet using the following command:
== Setting an RPC provider

[source,bash]
----
starkli declare target/dev/<NAME>.json --network=sepolia --compiler-version=2.1.0
----
In order to interact with Starknet, Starkli requires an RPC endpoint to be configured. For interactions with Starknet Sepolia and Starknet mainnet, Starkli supports default (and limited) RPC endpoints when using the `--network` flag. Configuring a custom RPC endpoint can be done by either using Starkli's `--rpc` flag or setting up Starkli's `STARKNET_RPC` environment variable (see more details in the https://book.starkli.rs/providers#using-an-rpc-url-directly[Starkli documentation]). To review all Starknet RPC providers, see xref:tools:api-services.adoc[API providers].

[NOTE]
====
The `--network` flag is used to specify the network you want to use, it could also be `mainnet` for example.
For demonstration purposes, this tutorial uses Starkli's default Starknet Sepolia RPC endpoint by setting `--network=sepolia`.

The `--compiler-version` flag is used to specify the version of the compiler you want to use. Starkli is currently running on version 2.6.x of the compiler.
====

== Declaring a smart contract

You can find the compiler version supported by Starkli by running:
A contract can be declared on Starknet using Starkli by running following command:

[source,bash]
----
starkli declare --help
starkli declare target/dev/<PROJECT_NAME>.sierra.json --network=sepolia
----

In the `--compiler-version` flag you will see possible versions of the compiler:
When using `starkli declare`, Starkli will do its best to identify the compiler version of the declared class. In case it fails, the `--compiler-version` flag can be used to specify the version of the compiler as follows:

. Find the compiler versions supported by Starkli by running:
+
[source,bash]
----
--compiler-version <COMPILER_VERSION>
Statically-linked Sierra compiler version [possible values: 2.0.1, 2.1.0]
starkli declare --help
----
+
and looking for the possible values of the `--compiler-version` flag.

However, the Scarb compiler version may be `2.2.0`, you can find this out by running:

. Find the current Scarb version in use:
+
[source,bash]
----
scarb --version
----

This is because Starkli and Scarb are not always in sync.

In this case you would need to use the compiler version that Starkli is using by installing a previous version of Scarb. See the https://github.com/software-mansion/scarb/releases[Scarb github repo] for more detail.
. In case a different compiler version is required, switch to a different Scarb version using `asdf`:

You can do this by running the following command for installing Scarb version `0.6.1`:
.. Install the desired Scarb version:
+
[source,bash]
----
asdf install scarb <VERSION>
----

.. Select the desired Scarb version as the local version for the project:
+
[source,bash]
----
curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | sh -s -- -v 0.6.1
asdf local scarb <VERSION>
----

If you were using a provider like Infura or Alchemy, the declaration command would look like this:
[TIP]
====
The following is an example of declaring a contract with both a a custom RPC endpoint (provided by https://www.infura.io/[Infura]) and a specific compiler version:

[source,bash]
----
starkli declare target/dev/contracts_Ownable.sierra.json \
starkli declare target/dev/<PROJECT_NAME>.sierra.json \
--rpc=https://starknet-sepolia.infura.io/v3/<API_KEY> \
--compiler-version=2.6.0
--compiler-version=2.6.0 \
----
====

== Expected result

The result of the declaration command is a contract class hash:
The output of a successful contract declaration using Starkli should resemble the following:

[source,bash]
----
Class hash declared: <CLASS_HASH>
----

This hash is the identifier of the contract class in Starknet. You can think of it as the address of the contract class. You can use a block explorer like https://sepolia.starkscan.co/class/0x00e68b4b07aeecc72f768b1c086d9b0aadce131a40a1067ffb92d0b480cf325d[StarkScan] to see the contract class hash in the blockchain.

If the contract you are declaring has previously been declared by someone else, you will get an output like this:
On the other hand, if the contract you are declaring has previously been declared, the output should resemble the following:

[source,bash]
----
Not declaring class as its already declared. Class hash: <CLASS_HASH>
----

This is because declaration is a one-time process for each unique contract code, and a contract's class hash is its unique identifier (for more details, see xref:architecture-and-concepts:smart-contracts/class-hash.adoc[Class hash]).

In both cases, however, you should be able to see the declared contract on a block explorer like https://sepolia.starkscan.co/[StarkScan] or https://sepolia.voyager.online/[Voyager] by searching for its class hash.