Getting Started
Basic Usage
Testing
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.
Deploying Smart Contracts with forge
Compilation with forge build --zksync
forge build --zksync
is used for compiling smart contracts into ZKsync VM bytecode.
The compiled files are stored in a structured directory at <PROJECT-ROOT>/zkout/
.
Command:
forge build [OPTIONS] --zksync
Options:
To get the list of all build
options run:
forge build --help
Besides standard options from original Foundry, there are ZKsync specific set of options:
--zk-startup[=<ENABLE_ZKVM_AT_STARTUP>]
Enable zkEVM at startup.--zk-compile[=<COMPILE_FOR_ZKVM>]
Compile for zkEVM.--zk-solc-path <ZK_SOLC_PATH>
Solc compiler path to use when compiling with zksolc.--zk-enable-eravm-extensions[=<ENABLE_ERAVM_EXTENSIONS>]
Enable the system contract compilation mode.--zk-force-evmla[=<FORCE_EVMLA>]
Forcibly switch to the EVM legacy assembly pipeline.--zk-llvm-options <LLVM_OPTIONS>
ZkSolc extra LLVM options.--zk-fallback-oz[=<FALLBACK_OZ>]
Try to recompile with -Oz if the bytecode is too large.--zk-detect-missing-libraries
Detect missing libraries, instead of erroring.-O, --zk-optimizer-mode <LEVEL>
Set the LLVM optimization parameter-O[0 | 1 | 2 | 3 | s | z]
. Use3
for best performance andz
for minimal size.--zk-optimizer
Enables optimizations.--zk-avoid-contracts <AVOID_CONTRACTS>
Contracts to avoid compiling on ZKsync.
Examples:
Compile with default settings or specify zksolc
version:
forge build --zksync
Deployment with forge create --zksync
Command:
forge create <CONTRACT> [OPTIONS] --zksync
forge create --zksync
deploys smart contracts to ZKsync.
Usage:
forge create <CONTRACT> [OPTIONS] --rpc-url <RPC-URL> --chain <CHAIN-ID> --account myKeystore --sender <KEYSTORE_ADDRESS> --zksync
Options:
To get the list of all create
options run:
forge create --help
Examples:
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" --account myKeystore --sender <KEYSTORE_ADDRESS> --rpc-url https://sepolia.era.zksync.dev --chain 300 --zksync
Verifying Contracts with forge
You can verify your contracts on the ZKsync block explorer using forge
by specifying the zksync
verifier and the appropriate verifier-url
.
Here's an example command:
forge create src/Greeter.sol:Greeter \
--constructor-args "Hello ZKsync" \
--account myKeystore \
--sender <KEYSTORE_ADDRESS> \
--rpc-url https://sepolia.era.zksync.dev \
--chain 300 \
--verifier zksync \
--verifier-url https://explorer.sepolia.era.zksync.dev/contract_verification \
--verify \
--zksync
Deploying Factory Contracts
To deploy contracts like GreeterFactory.sol
, use the --zk-enable-eravm-extensions
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 --zk-enable-eravm-extensions --zksync
Deploy GreeterFactory.sol
:
forge create src/GreeterFactory.sol:Factory --factory-deps src/Greeter.sol:Greeter --account myKeystore --sender <KEYSTORE_ADDRESS> --rpc-url https://sepolia.era.zksync.dev --chain 300 --zksync
Deploy Greeter.sol
via GreeterFactory.sol
:
cast send <FACTORY_ADDRESS> "CreateNewGreeter(string)" "ZKsync Rules" --account myKeystore --sender <KEYSTORE_ADDRESS> --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
Basic ZKsync Chain Interactions with cast
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.
Command:
cast <subcommand>
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> --account myKeystore --sender <KEYSTORE_ADDRESS> --chain <CHAIN-ID>
Example:
cast send 0xe34E488C1B0Fb372Cc4a5d39219261A5a6fc7996 "setGreeting(string)" "Hello, ZKsync!" --rpc-url https://sepolia.era.zksync.dev --account myKeystore --sender <KEYSTORE_ADDRESS> --chain 300
This command calls the setGreeting
function of a contract, updating the greeting to "Hello, ZKsync!".
Support
If you're having an issues creating Foundry ZKsync project, please check out list of issues in foundry-zksync
github issues page or reach out to us by creating a GitHub discussion.