Skip to content

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

  • Forge: Command-line tool to test, build, and deploy smart contracts
  • Cast: Swiss army knife for interacting with contracts, sending transactions, and getting chain data
  • Anvil: Local Ethereum node for development and testing
  • Chisel: Solidity REPL for testing code snippets

This page demonstrates how to set up Foundry to work with Polkadot Hub, including installation, compilation, deployment, and verification.

Before setting up Foundry, make sure you have:

  • A Unix-based operating system (Linux or macOS) or Windows with WSL
  • Git installed
  • A funded account on Polkadot Hub (see the Connect to Polkadot guide to get TestNet tokens)

To install the Foundry nightly build, run:

Terminal window
curl -L https://foundry.paradigm.xyz | bash

This installs foundryup, the Foundry toolchain installer. Then, run:

Terminal window
foundryup --version nightly

This installs the latest nightly versions of forge, cast, anvil, and chisel.

To verify the installation:

forge --version
forge Version: 1.6.0-nightly Commit SHA: 8b4f318e6a3e83a06dc4e989b9aba87894dca88e Build Timestamp: 2026-01-28T06:06:35.086737000Z (1769580395) Build Profile: dist

Create a new Foundry project:

Terminal window
forge init my-foundry-project
cd my-foundry-project

This creates a new directory with the following structure:

  • src/: Contains your Solidity smart contracts
  • script/: Holds deployment scripts
  • test/: Contains test files written in Solidity
  • lib/: Stores project dependencies
  • foundry.toml: Configuration file for Foundry settings

A sample Counter.sol contract will be created in the src/ directory along with a corresponding test file.

To compile your contracts, run:

Terminal window
forge build

You should see output similar to:

forge build
[⠊] Compiling... [⠒] Compiling 3 files with Solc 0.8.28 [⠢] Solc 0.8.28 finished in 1.23s Compiler run successful!

Forge compiles all contracts in the src/ directory and outputs the artifacts to the out/ directory.

Foundry's nightly build includes native support for Polkadot chains with polkadot-testnet, polkadot, and kusama as recognized chains with default RPC endpoints.

Create or modify your foundry.toml file:

foundry.toml
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc_version = "0.8.28"
[etherscan] # Contract verification configuration
polkadot-testnet = { key = "", url = "https://blockscout-testnet.polkadot.io/api?" }

With this configuration, you can use --chain polkadot-testnet in your commands without specifying the RPC URL explicitly.

Foundry's nightly build supports three Polkadot chains:

NetworkChain FlagBuilt-in RPC EndpointChain ID
Polkadot TestNet--chain polkadot-testnethttps://eth-rpc-testnet.polkadot.io420420417
Polkadot--chain polkadothttps://eth-rpc.polkadot.io420420419
Kusama--chain kusamahttps://kusama-asset-hub-eth-rpc.polkadot.io420420418

Create a .env file in your project root (make sure to add it to .gitignore):

.env
PRIVATE_KEY=INSERT_PRIVATE_KEY_HERE

Load the environment variables:

Terminal window
source .env

To deploy a contract to Polkadot Hub TestNet:

Terminal window
forge create src/Counter.sol:Counter \
--chain polkadot-testnet \
--rpc-url https://eth-rpc-testnet.polkadot.io \
--private-key $PRIVATE_KEY \
--broadcast

You'll see output with the deployed contract address:

forge create src/Counter.sol:Counter \
--chain polkadot-testnet --rpc-url https://eth-rpc-testnet.polkadot.io --private-key $PRIVATE_KEY --broadcast [⠊] Compiling... No files changed, compilation skipped Deployer: 0x3427D90f1Ee5c5D3627c2EBb37f90393526066fd Deployed to: 0xF1fbAf96A16458A512A33b31c4414C4a81f50EF4 Transaction hash: 0x1cba7b61c771192b297024766bed8b6e607f218e12899739fe61a3eed2690779

For more complex deployments, create a deployment script in the script/ directory:

script/Counter.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import {Script} from "forge-std/Script.sol";
import {Counter} from "../src/Counter.sol";
contract CounterScript is Script {
function run() external {
// Get the deployer's private key from environment
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
// Start broadcasting transactions
vm.startBroadcast(deployerPrivateKey);
// Deploy the contract
Counter counter = new Counter();
// Stop broadcasting
vm.stopBroadcast();
}
}

Run the deployment script:

Terminal window
forge script script/Counter.s.sol:CounterScript \
--chain polkadot-testnet \
--broadcast

The --broadcast flag tells Forge to submit the transactions to the network.

To verify your deployed contract on Polkadot Hub, use the verification feature with the Polkadot Hub explorer verifier.

Terminal window
forge verify-contract INSERT_CONTRACT_ADDRESS \
src/Counter.sol:Counter \
--chain polkadot-testnet

Blockscout does not require an API key. With Foundry's native Polkadot support, --verifier and --verifier-url are not needed.

You should see output similar to:

forge verify-contract 0xc29C4ebCdd1c49bc77362A13Ab921f22005828A0 \ src/Counter.sol:Counter \
--chain polkadot-testnet Start verifying contract 0xc29C4ebCdd1c49bc77362A13Ab921f22005828A0 deployed on polkadot-testnet Submitting verification for [src/Counter.sol:Counter] 0xc29C4ebCdd1c49bc77362A13Ab921f22005828A0. Submitted contract for verification: Response: OK GUID: c29c4ebcdd1c49bc77362a13ab921f22005828a0698f2622 URL: https://blockscout-testnet.polkadot.io/address/0xc29c4ebcdd1c49bc77362a13ab921f22005828a0

Replace INSERT_CONTRACT_ADDRESS with your deployed contract's address.

For contracts with constructor arguments:

Terminal window
forge verify-contract INSERT_CONTRACT_ADDRESS \
src/Counter.sol:Counter \
--chain polkadot-testnet \
--constructor-args $(cast abi-encode "constructor(uint256,address)" 42 INSERT_DEPLOYER_ADDRESS)

Replace INSERT_CONTRACT_ADDRESS with your deployed contract's address.

Cast is a powerful command-line tool for interacting with deployed contracts.

Terminal window
cast call INSERT_CONTRACT_ADDRESS "number()(uint256)" \
--chain polkadot-testnet
Terminal window
cast send INSERT_CONTRACT_ADDRESS "setNumber(uint256)" 42 \
--chain polkadot-testnet \
--private-key $PRIVATE_KEY
Terminal window
cast balance INSERT_ACCOUNT_ADDRESS --chain polkadot-testnet

For more complex interactions, create scripts in the script/ directory that can read and write contract state programmatically.

Foundry uses Solidity for writing tests, allowing you to test your contracts in the same language they're written in:

Terminal window
forge test

For verbose output showing gas usage and detailed logs:

Terminal window
forge test -vvv

Run specific tests:

Terminal window
forge test --match-test testIncrement

Run tests with gas reporting:

Terminal window
forge test --gas-report
  • Connect to Polkadot Hub


    View network details and learn how to connect your development tools to Polkadot Hub.

    → View Network Details

  • For Ethereum Developers


    Learn how smart contracts work on Polkadot Hub.

    → Get Started

Last updated: