Deploy on Zircuit
A tutorial for deploying a smart contract on Zircuit using Foundry
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 testnet ETH bridged to Zircuit testnet
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 installerUpdates your shell to recognize the new commands
Installs or updates
forge
,cast
,anvil
, andchisel
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/
├── foundry.toml # Foundry configuration file
├── src/ # Smart contract source files
│ └── Counter.sol # Main contract
├── script/ # Deployment scripts
│ └── Counter.s.sol # Deployment script
├── test/ # Test files
│ └── Counter.t.sol # Contract tests
└── lib/ # Dependencies (like node_modules)
Project structure explained:
src/
: Contains your Solidity smart contractsscript/
: Contains deployment scripts written in Soliditytest/
: Contains test files for your contractslib/
: Contains external dependenciesfoundry.toml
: Configuration file for compiler settings, networks, etc.
3. Set Up Your Private Key for Deployment
Never use your mainnet private key for testing. Always use a separate wallet for testnet development.
You need to securely store your private key for contract deployment:
# Import your private key securely
cast wallet import defaultKey --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
Alternative methods:
# Using environment variable (less secure)
export PRIVATE_KEY=0x...
# Using keystore file
cast wallet import mykey --keystore /path/to/keystore
4. Compile Your Smart Contract
Compile all contracts in your project:
forge compile
What this does:
Compiles all
.sol
files in thesrc/
directoryGenerates ABI (Application Binary Interface) files
Creates bytecode for deployment
Checks for compilation errors and warnings
Outputs artifacts to
out/
directory
Expected output:
[⠊] Compiling...
[⠢] Compiling 3 files with 0.8.19
[⠆] Solc 0.8.19 finished in 1.2s
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 functionsetNumber()
: Allows setting the counter to any valueincrement()
: Increases the counter by 1All functions are
public
, meaning anyone can call them
// 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 utilitiesvm.startBroadcast()
: Begins recording transactions to broadcast to the networknew Counter()
: Deploys a new instance of the Counter contractvm.stopBroadcast()
: Stops recording transactions
6. Deploy Your Smart Contract
Deploy the contract to Zircuit Garfield Testnet:
forge script script/Counter.s.sol:CounterScript \
--rpc-url https://garfield-testnet.zircuit.com \
--account defaultKey \
--broadcast
Command breakdown:
forge script
: Command to run deployment scriptsscript/Counter.s.sol:CounterScript
: Path to script file and contract name--rpc-url
: The RPC endpoint for Zircuit testnet--account defaultKey
: Uses the imported private key--broadcast
: Actually sends transactions to the network
Expected output:
[⠊] 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://garfield-testnet.zircuit.com \
--account defaultKey
Replace <CONTRACT_ADDRESS>
with your actual contract address from step 6.
What this does:
Sends a transaction to call the
increment()
functionUses your imported private key to sign the transaction
Pays gas fees for the transaction
Expected output:
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):
cast call <CONTRACT_ADDRESS> "number()" \
--rpc-url https://garfield-testnet.zircuit.com
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:
cast send <CONTRACT_ADDRESS> "setNumber(uint256)" 42 \
--rpc-url https://garfield-testnet.zircuit.com \
--account defaultKey
Check the balance of your deployer address:
cast balance <YOUR_WALLET_ADDRESS> \
--rpc-url https://garfield-testnet.zircuit.com
Get transaction details:
cast tx <TRANSACTION_HASH> \
--rpc-url https://garfield-testnet.zircuit.com
8. Advanced Features and Next Steps
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
Configuration
Customize your foundry.toml
for different networks:
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
# Zircuit testnet configuration
[rpc_endpoints]
zircuit_testnet = "https://garfield-testnet.zircuit.com"
[etherscan]
zircuit_testnet = { key = "${ZIRCUIT_API_KEY}" }
Troubleshooting
Common Issues
"Account not found": Make sure you've imported your private key correctly
"Insufficient funds": Ensure your wallet has enough testnet ETH
"Compilation failed": Check your Solidity syntax and version compatibility
"RPC connection failed": Verify the RPC URL is correct and accessible
Getting Help
Foundry Book: Comprehensive documentation
Foundry GitHub: Issues and discussions
Last updated
Was this helpful?