Tutorial: Your First Foundry Project
Follow this guide to experience the full Blocktools workflow, from creating a new smart contract to securing, testing, and forecasting its costs.
This tutorial will give you a hands-on feel for how the Blocktools suite works together to create a seamless and powerful development experience. By the end, you'll have the confidence to integrate these tools into your own projects.
Prerequisites
- Foundry is installed.
- The Blocktools suite is installed.
- (Optional but Recommended) An Alchemy API key for connecting to live networks.
Pro Tip: Managing Your API Keys
You'll never need to hardcode a private key or API secret. Blocktools offers three flexible ways to provide your keys, checked in this order of priority:
- Command-Line Flag (Highest Priority):
For one-off use. Example:gas-forecaster deploy ... --api-key YOUR_KEY
- Environment Variables (Recommended):
The best method for most developers. Set them once in your shell's configuration file (e.g.,.zshrc
,.bash_profile
), and all your tools will automatically detect them.export ALCHEMY_API_KEY="your_alchemy_api_key" export ETHERSCAN_API_KEY="your_etherscan_api_key"
- Global Config File (Set it and Forget it):
For a permanent, system-wide setting, you can use a tool's built-inconfig
command. This saves your keys to a central file at~/.config/blocktools/config.toml
where all tools can access them.# Use this command once to save your key permanently $ receipt-parse config set alchemy_api_key YOUR_KEY_HERE API key saved successfully.
For this tutorial, we'll assume you have configured your Alchemy key using one of these methods.
Step 1: Create a New Foundry Project
First, let's use Foundry's `forge` command to initialize a new project.
$ forge init my-secure-counter
$ cd my-secure-counter
Foundry creates a default contract at src/Counter.sol
. This is the contract we will analyze and improve.
Step 2: Security First with `sol-sentry`
Before we even think about deploying, let's run a security scan on the default contract. A professional workflow always starts with security.
$ sol-sentry scan src/Counter.sol
sol-sentry
will immediately find two high-severity issues! It correctly identifies that the `increment()` and `setNumber()` functions are public and change the contract's state without any access control. Anyone could call them.
Let's fix this by implementing the standard `Ownable` pattern. Replace the content of src/Counter.sol
with this secure version:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract Counter {
uint256 public number;
address public owner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Not the owner");
_;
}
function setNumber(uint256 newNumber) public onlyOwner {
number = newNumber;
}
function increment() public onlyOwner {
number++;
}
}
Now, run the scan again. You will be greeted with a much better result:
$ sol-sentry scan src/Counter.sol
✅ No issues found. Your project looks safe to deploy.
In just a few seconds, you've identified and fixed a critical security flaw. That's the power of `sol-sentry`.
Step 3: Forecast Costs with `gas-forecaster`
Now that our contract is secure, let's find out what it would cost to deploy it to various networks.
$ gas-forecaster deploy src/Counter.sol
The tool compiles your contract and provides a clean, easy-to-read table of estimated deployment costs in USD across Ethereum, Polygon, Arbitrum, and other major chains. You now have a clear budget before writing a single line of deployment script.
Step 4: Interactive Testing with `sol-console`
It's time to interact with our contract. Instead of writing a complex script, let's use `sol-console` to launch a local test node and get an interactive REPL.
# This one command starts a local node, compiles, and deploys your contract
$ sol-console --contract-path src/Counter.sol --standalone
You are now inside a live console connected to your deployed contract. Let's try calling some functions.
# Check the initial value
contract.number()
<-- Return Value: 0
# Increment the number
contract.increment()
✅ Transaction Confirmed
- Status: Success
- Gas Used: ...
# Check the new value
contract.number()
<-- Return Value: 1
This provides an incredibly fast feedback loop for testing and debugging your contract's logic without ever leaving the terminal. Type exit
to close the console.
Conclusion & Next Steps
Congratulations! You have successfully used the Blocktools suite to secure, analyze, and test a smart contract from scratch. You've experienced how each tool addresses a specific part of the development lifecycle, working together to make you a more effective and secure Web3 developer.
Now that you have a feel for the workflow, we encourage you to explore the detailed documentation for each tool to learn about their advanced features.