Creating a Stylus project

For a full Stylus quickstart (installation, contract deployment, CLI usage, etc.), refer to the official Arbitrum docs: Stylus Quickstartarrow-up-right

cargo stylusarrow-up-right is a CLI toolkit built to facilitate the development of Stylus contracts.

It is available as a plugin to the standard cargo tool used for developing Rust programs.

Installing cargo stylus

In your terminal, run:

cargo install --force cargo-stylus

Add WASM (WebAssemblyarrow-up-right) as a build target for the specific Rust toolchain you are using. The below example sets your default Rust toolchain to 1.80 as well as adding the WASM build target:

rustup default 1.80
rustup target add wasm32-unknown-unknown --toolchain 1.80

You can verify that cargo stylus is installed by running cargo stylus --help in your terminal, which will return a list of helpful commands, we will use some of them in this guide:

cargo stylus --help returns:

Cargo command for developing Stylus projects

Usage: cargo stylus <COMMAND>

Commands:
  new         Create a new Stylus project
  init        Initializes a Stylus project in the current directory
  export-abi  Export a Solidity ABI
  activate    Activate an already deployed contract [aliases: a]
  cache       Cache a contract using the Stylus CacheManager for Arbitrum chains
  check       Check a contract [aliases: c]
  deploy      Deploy a contract [aliases: d]
  verify      Verify the deployment of a Stylus contract [aliases: v]
  cgen        Generate c code bindings for a Stylus contract
  replay      Replay a transaction in gdb [aliases: r]
  trace       Trace a transaction [aliases: t]
  help        Print this message or the help of the given command(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

Creating a project

Let's create our first Stylus project by running:

cargo stylus new generates a starter template that implements a Rust version of the Solidity Counter smart contract example:

At this point, you can move on to the next step of this guide or develop your first Rust smart contract. Feel free to use the Stylus Rust SDK reference sectionarrow-up-right as a starting point; it offers many examples to help you quickly familiarize yourself with Stylus.

Checking if your Stylus project is valid

By running cargo stylus check against your first contract, you can check if your program can be successfully deployed and activated onchain.

Important

Ensure your Docker service runs so this command works correctly.

cargo stylus check executes a dry run on your project by compiling your contract to WASM and verifying if it can be deployed and activated onchain.

If the command above fails, you'll see detailed information about why your contract would be rejected:

The contract can fail the check for various reasons (on compile, deployment, etc...). Reading the Invalid Stylus WASM Contracts explainerarrow-up-right can help you understand what makes a WASM contract valid or not.

If your contract succeeds, you'll see something like this:

Note that running cargo stylus check may take a few minutes, especially if you're verifying a contract for the first time.

See cargo stylus check --help for more options.

Deploying your contract

Once you're ready to deploy your contract onchain, cargo stylus deploy will help you with the deployment and its gas estimation.

Estimating gas

Note: For every transaction, we'll use the testnode pre-funded wallet, you can use 0xb6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659 as your private key.

You can estimate the gas required to deploy your contract by running:

The command should return something like this:

Deployment

Let's move on to the contract's actual deployment. Two transactions will be sent onchain: the contract deployment and its activation.

Once the deployment and activations are successful, you'll see an output similar to this:

Make sure to save the contract's deployment address for future interactions!

More options are available for sending and outputting your transaction data. See cargo stylus deploy --help for more details.

Exporting the Solidity ABI interface

The cargo stylus tool makes it easy to export your contract's ABI using cargo stylus export-abi.

This command returns the Solidity ABI interface of your smart contract. If you have been running cargo stylus new without modifying the output, cargo stylus export-abi will return:

Ensure you save the console output to a file that you'll be able to use with your dApp.

Interacting with your Stylus contract

Stylus contracts are EVM-compatible, you can interact with them with your tool of choice, such as Hardhatarrow-up-right, Foundry's Castarrow-up-right, or any other Ethereum-compatible tool.

In this example, we'll use Foundry's Cast to send a call and then a transaction to our contract.

Calling your contract

Our contract is a counter; in its initial state, it should store a counter value of 0. You can call your contract so it returns its current counter value by sending it the following command:

Call to the function: number()(uint256)

Let's break down the command:

  • cast call command sends a call to your contract

  • The --rpc-url option is the RPC URL endpoint of our testnode: http://localhost:8547arrow-up-right

  • The --private-key option is the private key of our pre-funded development account. It corresponds to the address 0x3f1eae7d46d88f08fc2f8ed27fcb2ab183eb2d0e

  • The [deployed-contract-address] is the address we want to interact with, it's the address that was returned by cargo stylus deploy

  • number()(uint256) is the function we want to call in Solidity-style signature. The function returns the counter's current value

Calling 'number()(uint256)' returns:

The number()(uint256) function returns a value of 0, the contract's initial state.

Sending a transaction to your contract

Let's increment the counter by sending a transaction to your contract's increment() function. We'll use Cast's send command to send our transaction.

Sending a transaction to the function: increment()

Transaction returns:

Testing your contract

The Stylus testing framework includes TestVM, a simulation of the Stylus execution environment that enables you to test your contracts without deploying them. Here's a simple example of how to test the counter contract:

To enable testing, you'll need to add the following to your Cargo.toml:

Running your tests

You can run your tests using the standard Rust test command:

The testing framework allows you to:

  • Simulate transaction context and block information

  • Test contract storage operations

  • Verify state transitions

  • Mock contract-to-contract interactions

  • Test various scenarios without deployment costs

For more advanced testing techniques and best practices, see the Testing contracts with Stylus guidearrow-up-right.

Last updated