Appearance
Using Foundry with IOST Layer 2
This guide explains how to use Foundry - a blazing fast, portable Rust-based toolkit for Ethereum application development - to deploy and interact with smart contracts on IOST 3.0 Layer 2.
What is Foundry?
Foundry is a smart contract development toolchain written in Rust that includes:
- forge: A testing framework for Ethereum contracts
- cast: A command-line tool for interacting with EVM smart contracts
- anvil: A local Ethereum node for development purposes
- chisel: A Solidity REPL for quick experimentation
Compared to other development environments, Foundry offers:
- Extremely fast compilation and testing
- Native Solidity testing
- Advanced debugging and gas profiling tools
- Strong focus on unit and integration testing
Installation
Install Foundry with the following commands:
bash
# Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup
# Verify installation
forge --version
cast --version
anvil --version
Project Setup
Create a new Foundry project for use with IOST Layer 2:
bash
# Create a new project
forge init my_iost_project
cd my_iost_project
# Install OpenZeppelin contracts (optional but recommended)
forge install OpenZeppelin/openzeppelin-contracts
Configuration for IOST Layer 2
Update your foundry.toml
file to include IOST Layer 2 network settings:
toml
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.19"
optimizer = true
optimizer_runs = 200
[rpc_endpoints]
iost_mainnet = "https://l2-mainnet.iost.io"
[etherscan]
iost_mainnet = { url = "https://l2-scan.iost.io/" }
Writing Contracts
Create your Solidity contracts in the src
directory:
solidity
// src/SimpleStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract SimpleStorage {
uint256 private value;
event ValueChanged(uint256 newValue);
function set(uint256 newValue) public {
value = newValue;
emit ValueChanged(newValue);
}
function get() public view returns (uint256) {
return value;
}
}
Writing Tests
Create test files in the test directory using Solidity (one of Foundry's key advantages):
solidity
// test/SimpleStorage.t.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Test.sol";
import "../src/SimpleStorage.sol";
contract SimpleStorageTest is Test {
SimpleStorage public simpleStorage;
function setUp() public {
simpleStorage = new SimpleStorage();
}
function testSetValue() public {
simpleStorage.set(100);
assertEq(simpleStorage.get(), 100);
}
function testEmitsEvent() public {
vm.expectEmit(true, true, true, true);
emit SimpleStorage.ValueChanged(200);
simpleStorage.set(200);
}
}
Run your tests with:
bash
forge test -vv
Creating Deployment Scripts
Foundry uses Solidity scripts for deployment. Create a script file:
solidity
// script/DeploySimpleStorage.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Script.sol";
import "../src/SimpleStorage.sol";
contract DeploySimpleStorage is Script {
function run() public {
// Retrieve private key from environment
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
// Start broadcasting transactions
vm.startBroadcast(deployerPrivateKey);
// Deploy the contract
SimpleStorage simpleStorage = new SimpleStorage();
// Stop broadcasting transactions
vm.stopBroadcast();
// Log the deployed contract address
console.log("SimpleStorage deployed to:", address(simpleStorage));
}
}
Deployment to IOST Layer 2
To deploy your contract to IOST Layer 2:
- Set your private key as an environment variable:
bash
export PRIVATE_KEY=your_private_key_here
- Deploy using forge:
bash
forge script script/DeploySimpleStorage.s.sol --rpc-url iost_mainnet --broadcast
Contract Verification
Verify your contract on the IOST Layer 2 explorer:
bash
forge verify-contract \
--chain-id 182 \
--compiler-version v0.8.19 \
--watch \
--verifier-url https://l2-scan.iost.io/ \
<DEPLOYED_CONTRACT_ADDRESS> \
src/SimpleStorage.sol:SimpleStorage
Interacting with Deployed Contracts
Foundry's cast
command allows you to interact with your deployed contracts:
bash
# Read the current value
cast call <CONTRACT_ADDRESS> "get()" --rpc-url iost_mainnet
# Set a new value
cast send --private-key $PRIVATE_KEY <CONTRACT_ADDRESS> "set(uint256)" 123 --rpc-url iost_mainnet
Advanced Features
Gas Profiling
Analyze gas usage of your contract functions:
bash
forge test --gas-report
Fuzz Testing
Foundry provides powerful property-based testing:
solidity
function testFuzz_SetValue(uint256 x) public {
simpleStorage.set(x);
assertEq(simpleStorage.get(), x);
}
Traces
Debug your contract with detailed execution traces:
bash
forge test -vvvv
Fork Testing
Test against a fork of the IOST Layer 2 mainnet:
bash
forge test --fork-url https://l2-mainnet.iost.io
Troubleshooting
RPC Connectivity Issues
Symptom: Unable to connect to IOST Layer 2 network
Solution: Verify RPC URL and network status
Verification Failures
Symptom: Contract verification fails on the explorer
Solution: Ensure compiler version and optimization settings match deployment parameters exactly
Gas Estimation Errors
Symptom: Deployment fails with gas estimation errors
Solution: Add explicit gas limits to your deployment command with --gas-limit
Best Practices
- Use Consistent Solidity Versions: Keep the same compiler version across your project
- Leverage Foundry's Testing Features: Use Solidity for tests to benefit from type checking
- Store Sensitive Data in .env: Never commit private keys to version control
- Use Script Libraries: Leverage the forge-std Script base for deployments
- Gas Optimization: Regularly run gas reports to identify optimization opportunities