Deploy on Zircuit

A tutorial for deploying a smart contract on Zircuit using Foundry

Note that SLS is not enabled while we focus on Zircuit Finance. Zircuit Finance does not rely on the Zircuit chain.

This tutorial will guide you through the complete process of setting up Foundry, creating a smart contract, and deploying it to the Zircuit testnet. Foundry is a powerful, fast, and portable toolkit for Ethereum application development written in Rust.

Prerequisites

Before starting, ensure you have:

  • A Unix-like operating system (macOS, Linux, or WSL on Windows)

  • Git installed

  • A wallet with some ETH on Zircuit

  • Basic understanding of Solidity and blockchain concepts

What is Foundry?

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development. It consists of:

  • Forge: Ethereum testing framework (like Truffle, Hardhat)

  • Cast: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data

  • Anvil: Local Ethereum node, akin to Ganache, Hardhat Network

  • Chisel: Fast, utilitarian, and verbose Solidity REPL

1

Set Up Foundry

First, we'll install Foundry using the official installer script:

# Download and install Foundry
curl -L https://foundry.paradigm.xyz | bash

# Reload your shell configuration to make foundryup available
source ~/.zshrc  # for zsh users
# OR
source ~/.bashrc  # for bash users

# Install the latest version of Foundry tools
foundryup

What this does:

  • Downloads the Foundry installer script

  • Installs foundryup, the Foundry toolchain installer

  • Updates your shell to recognize the new commands

  • Installs or updates forge, cast, anvil, and chisel

Verify installation:

forge --version
2

Create a New Counter Project

Initialize a new Foundry project with the counter template:

# Create a new Foundry project called 'counter'
forge init counter

# Navigate into the project directory
cd counter

What this creates:

counter/
├── lib/               # Dependencies (like node_modules)
├── script/            # Deployment scripts
│   └── Counter.s.sol  # Deployment script
├── src/               # Smart contract source files
│   └── Counter.sol    # Main contract
├── test/              # Test files
│   └── Counter.t.sol  # Contract tests
└── foundry.toml       # Foundry configuration file
3

Set Up Your Private Key for Deployment

You need to securely store your private key for contract deployment:

cast wallet import mainnetKey --interactive

What this does:

  • Prompts you to enter your private key securely (won't display on screen)

  • Encrypts and stores the key locally under the name "defaultKey"

  • Requires a password to encrypt the stored key

4

Compile Your Smart Contract

Compile all contracts in your project:

forge compile

What this does:

  • Compiles all .sol files in the src/ directory

  • Generates ABI (Application Binary Interface) files

  • Creates bytecode for deployment

  • Checks for compilation errors and warnings

  • Outputs artifacts to out/ directory

Expected output:

[⠊] Compiling...
[⠃] Compiling 23 files with Solc 0.8.30
[⠊] Solc 0.8.30 finished in 889.13ms
Compiler run successful!
5

Review the Contract and Deployment Script

Let's examine the smart contract and deployment script in detail:

src/Counter.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Counter {
    // State variable to store the counter value
    uint256 public number;

    // Function to set the counter to a specific value
    function setNumber(uint256 newNumber) public {
        number = newNumber;
    }

    // Function to increment the counter by 1
    function increment() public {
        number++;
    }
}

Contract explanation:

  • uint256 public number: A public state variable that automatically generates a getter function

  • setNumber(): Allows setting the counter to any value

  • increment(): Increases the counter by 1

  • All functions are public, meaning anyone can call them

script/Counter.s.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script} from "forge-std/Script.sol";
import {Counter} from "../src/Counter.sol";

contract CounterScript is Script {
    Counter public counter;

    function setUp() public {}

    function run() public {
        // Start recording transactions for broadcast
        vm.startBroadcast();
        
        // Deploy the Counter contract
        counter = new Counter();
        
        // Stop recording transactions
        vm.stopBroadcast();
    }
}

Deployment script explanation:

  • Inherits from Script to access deployment utilities

  • vm.startBroadcast(): Begins recording transactions to broadcast to the network

  • new Counter(): Deploys a new instance of the Counter contract

  • vm.stopBroadcast(): Stops recording transactions

6

Deploy Your Smart Contract

Customize your foundry.toml for different networks:

[profile.default]
src = "src"
out = "out"
libs = ["lib"]

# Zircuit RPC configuration
[rpc_endpoints]
zircuit_mainnet = "https://mainnet.zircuit.com"
garfield_testnet = "https://garfield-testnet.zircuit.com"

Deploy the contract to Zircuit

forge script script/Counter.s.sol:CounterScript \
    --rpc-url zircuit_mainnet \
    --account mainnetKey \
    --broadcast

Command breakdown:

  • forge script: Command to run deployment scripts

  • script/Counter.s.sol:CounterScript: Path to script file and contract name

  • --rpc-url: The RPC endpoint

  • --account <key>: Uses the imported private key

  • --broadcast: Actually sends transactions to the network

Expected output (Garfield Testnet):

[⠊] Compiling...
No files changed, compilation skipped
Enter keystore password:
Script ran successfully.

## Setting up 1 EVM.

==========================

Chain 48898

Estimated gas price: 0.000000509 gwei

Estimated total gas used for script: 203856

Estimated amount required: 0.000000000103762704 ETH

==========================

##### 48898
✅  [Success] Hash: 0x59bf94e4055ee2c4a71b9e6a7b7589ad3a5831ac38717c5f0d488eb4ed365a77
Contract Address: 0x6E69d4f9bc6a3E2f67d2D86877800482A8cdca40
Block: 8549829
Paid: 0.000000000039987315 ETH (156813 gas * 0.000000255 gwei)

✅ Sequence #1 on 48898 | Total Paid: 0.000000000039987315 ETH (156813 gas * avg 0.000000255 gwei)

Copy the Contract Address from the output - you'll need it for the next step!

7

Interact with Your Smart Contract

Now that your contract is deployed, you can interact with it using cast.

Execute a State-Changing Function

To call the increment() function (which costs gas):

cast send <CONTRACT_ADDRESS> "increment()" \
    --rpc-url https://mainnet.zircuit.com \
    --account mainnetKey

Replace <CONTRACT_ADDRESS> with your actual contract address from step 6.

What this does:

  • Sends a transaction to call the increment() function

  • Uses your imported private key to sign the transaction

  • Pays gas fees for the transaction

Expected output (Garfield Testnet):

blockHash            0x97162a12dc900daf598e18c7a026d0b7bea5b121fc20bd99600292b53ba8148b
blockNumber          8550305
contractAddress      
cumulativeGasUsed    91965
effectiveGasPrice    255
from                 0xbd9B49deFc88AC16D7fC0F7FE6Eb7E0F54F6317f
gasUsed              43482
...

Read Contract State

To read the current value of number (free, no gas required):

Expected output:

0x0000000000000000000000000000000000000000000000000000000000000001

This hexadecimal output represents the number 1, showing that our increment worked!

To convert hex to decimal:

cast --to-dec 0x0000000000000000000000000000000000000000000000000000000000000001
# Output: 1

Additional Interaction Examples

Set the counter to a specific value:

Check the balance of your deployer address:

Get transaction details:

8

Verifying Contracts

After doing programmatic interactions with the smart contract, you can also verify the contract using forge.

forge verify-contract <CONTRACT_ADDRESS> <SOURCE_FILE>:<CONTRACT_NAME> \
--chain-id 48900 \
--verifier sourcify \
--verifier-url https://sourcify.dev/server

https://explorer.zircuit.com/address/<CONTRACT_ADDRESS>

9

Advanced Features

Running Tests

Foundry includes a powerful testing framework:

# Run all tests
forge test

# Run tests with verbose output
forge test -vvv

# Run specific test
forge test --match-test testIncrement

Code Coverage

Generate test coverage reports:

forge coverage

Gas Reporting

Get detailed gas usage reports:

forge test --gas-report

Gas Reporting

Get detailed gas usage reports:

forge test --gas-report

Last updated

Was this helpful?