Getting Started
Prerequisites
The primary prerequisite for using foundry-zksync
is the Rust Compiler.
Installation Guide
To integrate foundry-zksync
into your projects, you have the flexibility to install its components individually or the entire suite at once. Follow the steps below to get started:
- Clone the repository:
git clone git@github.com:matter-labs/foundry-zksync.git
- Navigate to the project directory:
cd foundry-zksync
- Prepare the Installation Script: Ensure the script is executable
chmod +x ./install-foundry-zksync
- Run the Installer: Execute the script to install the foundry-zksync binaries forge and cast
./install-foundry-zksync
Once the forge
and cast
binaries are installed, you can start using foundry-zksync
. Source your preferred profile or refresh your terminal window to activate the changes. You are now ready to begin working with foundry-zksync
!
For component-specific installations from source:
- Forge: To install, execute:
cargo install --path ./crates/forge --profile local --force --locked
- Cast: To install, run:
cargo install --path ./crates/cast --profile local --force --locked
For the entire suite:
- Execute the following command for a comprehensive installation:
cargo build --release
Choose the installation that best fits your development needs.
Configuration
Initial Setup
After installation, initialize a new project with forge init <project_name>
, which sets up the basic structure of a new Foundry project.
foundry.toml
Project Configuration using Foundry is designed to be very configurable. You can configure Foundry using a file called foundry.toml
in the root of your project, or any other parent directory.
Configuration can be arbitrarily namespaced by profiles. The default profile is named default
.
You can select another profile using the FOUNDRY_PROFILE
environment variable. You can also override parts of your configuration using FOUNDRY_
or DAPP_
prefixed environment variables, like FOUNDRY_SRC
.
forge init
creates a basic, extendable foundry.toml
file.
To see your current configuration, run forge config
. To see only basic options (as set with forge init
), run forge config --basic
. This can be used to create a new foundry.toml
file with forge config --basic > foundry.toml
.
By default forge config
shows the currently selected foundry profile and its values. It also accepts the same arguments as forge build
. An example foundry.toml
for zkSync with zksolc configurations may look like:
[profile.default]
src = 'src'
out = 'out'
libs = ['lib']
[profile.zksync]
src = 'src'
libs = ['lib']
fallback_oz = true
is_system = false
mode = "3"
Basic Usage
Running Tests
Use forge test --zksync
to run tests written for your smart contracts. For an overview of how to write tests using foundry-zksync
please refer to Foundry testing here.
forge
Deploying Smart Contracts with forge build --zksync
Compilation with forge build --zksync
is used for compiling smart contracts into zkEVM bytecode. The compiled files are stored in a structured directory at <PROJECT-ROOT>/zkout/
.
Usage:
forge build [OPTIONS] --zksync
Key Compiler Options:
--use-zksolc <ZK_SOLC_VERSION>
: Specify the zksolc version or a local zksolc path.--is-system <SYSTEM_MODE>
: Enables system contract compilation mode (true
/false
).--force-evmla <FORCE_EVMLA>
: Switch to the EVM legacy assembly pipeline.--fallback-oz <FALLBACK_OZ>
: Recompile with-Oz
if bytecode is too large.--detect-missing-libraries
: Detect and report missing libraries.-O, --optimization <LEVEL>
: Set LLVM optimization levels.--zk-optimizer
: Optimize specifically for zkSync.
Example Usage: Compile with default settings or specify zksolc
version:
forge build --zksync
forge create --zksync
Deployment with forge create --zksync
deploys smart contracts to zkSync.
Usage:
forge create <CONTRACT> [OPTIONS] --rpc-url <RPC-URL> --chain <CHAIN-ID> --private-key <PRIVATE-KEY> --zksync
Options:
--constructor-args <ARGS>
: Specify constructor arguments.--constructor-args-path <FILE>
: File path for constructor arguments.<CONTRACT>
: Contract identifier in<path>:<contractname>
format.--factory-deps <FACTORY-DEPS>
: Specify factory dependencies.
Example: Deploy Greeter.sol
to zkSync Sepolia testnet:
Click to view the `Greeter.sol` contract
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
contract Greeter {
string private greeting;
constructor(string memory _greeting) {
greeting = _greeting;
}
function greet() public view returns (string memory) {
return greeting;
}
function setGreeting(string memory _greeting) public {
greeting = _greeting;
}
}
forge create src/Greeter.sol:Greeter --constructor-args "Hello zkSync" --private-key <PRIVATE_KEY> --rpc-url https://sepolia.era.zksync.dev --chain 300 --zksync
Deploying Factory Contracts
To deploy contracts like GreeterFactory.sol
, use the is-system
flag.
Click to view the `GreeterFactory.sol` contract
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "./Greeter.sol";
contract Factory {
Greeter[] public GreeterArray;
function CreateNewGreeter(string memory _greeting) public {
Greeter greeter = new Greeter(_greeting);
GreeterArray.push(greeter);
}
function gfSetter(uint256 _greeterIndex, string memory _greeting) public {
Greeter(address(GreeterArray[_greeterIndex])).setGreeting(_greeting);
}
function gfGetter(uint256 _greeterIndex) public view returns (string memory) {
return Greeter(address(GreeterArray[_greeterIndex])).greet();
}
}
Compile GreeterFactory.sol
:
forge build --is-system=true --zksync
Deploy GreeterFactory.sol
:
forge create src/GreeterFactory.sol:Factory --factory-deps src/Greeter.sol:Greeter --private-key <PRIVATE_KEY> --rpc-url https://sepolia.era.zksync.dev --chain 300 --zksync
Deploy Greeter.sol
via GreeterFactory.sol
:
cast send <FACTORY_ADDRESS> "CreateNewGreeter(string)" "zkSync Rules" --private-key <PRIVATE_KEY> --rpc-url https://sepolia.era.zksync.dev --chain 300
Interact with Greeter.sol
cast call <CONTRACT_ADDRESS> "greet()(string)" --rpc-url https://sepolia.era.zksync.dev --chain 300
Output:
0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c7a6b53796e632052756c65730000000000000000000000000000000000000000
To decode the output to a readable string:
cast to-ascii 0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c7a6b53796e632052756c65730000000000000000000000000000000000000000
Output:
zkSync Rules
cast
Basic zkSync Chain Interactions with Introduction
This guide introduces you to fundamental interactions within the zkSync chain using cast
, a component of the foundry-zksync
toolkit. Learn how to query chain IDs, retrieve client versions, check L2 ETH balances, obtain gas prices, and more.
Chain ID Retrieval
Local Node:
Retrieve the Chain ID for a local zkSync node with:
cast chain-id --rpc-url http://localhost:3050
Expected Output:
270
, indicating the Chain ID of your local zkSync node.zkSync Sepolia Testnet:
For the zkSync Sepolia Testnet, use:
cast chain-id --rpc-url https://sepolia.era.zksync.dev
Expected Output:
300
, the Chain ID for the zkSync Sepolia Testnet.
Client Version Information
Knowing the client version is vital for compatibility checks and debugging:
cast client --rpc-url https://sepolia.era.zksync.dev
Expected Output: zkSync/v2.0
, denoting the client version.
L2 Balance Check
Verify the Layer 2 (L2) balance of an account:
cast balance 0x8b1d48a69ACEbC6eb201e2F4d162A002203Bfe8E --rpc-url https://sepolia.era.zksync.dev
Expected Output: A numerical value, e.g., 774909739323110932
, representing the account's L2 balance.
Current Gas Price
Fetch the current gas price on the network for transaction cost estimations:
cast gas-price --rpc-url https://sepolia.era.zksync.dev
Expected Output: A value such as 100000000
, indicating the current gas price.
Latest Block Details
Gain insights into the latest block on the zkSync chain:
cast block latest --rpc-url https://sepolia.era.zksync.dev
Expected Output: Detailed information about the latest block, including base fee per gas, gas limit, block hash, and more.
Sending Transactions
Initiate transactions, such as contract function calls, using cast
:
cast send <CONTRACT_ADDRESS> <FUNCTION_SIGNATURE> <ARGUMENTS> --rpc-url <RPC-URL> --private-key <PRIVATE-KEY> --chain <CHAIN-ID>
Example:
cast send 0xe34E488C1B0Fb372Cc4a5d39219261A5a6fc7996 "setGreeting(string)" "Hello, zkSync!" --rpc-url https://sepolia.era.zksync.dev --private-key <PRIVATE-KEY> --chain 300
This command calls the setGreeting
function of a contract, updating the greeting to "Hello, zkSync!". Replace <PRIVATE-KEY>
with your actual private key.