昨天 Zksync 上线了 Era 主网,在测试的时候想部署合约试试,结果发现直接使用 Remix 无法部署合约
查阅了文档才发现 Zksync Era 和 EVM 部署合约的流程不一样,甚至有自己的一套 sol 编译方法
先试了用 python 来部署发现不太行,python-sdk 和节点的 RPC 似乎还没有对齐,所以在使用的时候会报错。最后是用 Hardhat 部署上去了,踩坑一晚上,社区也还没有相关的提问所以分享一下。
hardhat 需要在 yarn 中配置,需要预先配置 yarn 环境
然后创建一个目录作为工作目录,并且使用 yarn 配置好 zksync 的 hardhat环境
mkdir example
cd example
yarn init -y
yarn add -D typescript ts-node @types/node ethers@^5.7.2 zksync-web3 @ethersproject/hash @ethersproject/web hardhat @matterlabs/hardhat-zksync-solc @matterlabs/hardhat-zksync-deploy
最后输入 yarn
命令初始化一下环境
在这个工作目录下创建 hardhat.config.ts
文件
import "@matterlabs/hardhat-zksync-deploy";
import "@matterlabs/hardhat-zksync-solc";
module.exports = {
zksolc: {
version: "1.3.5",
compilerSource: "binary",
settings: {},
},
defaultNetwork: "zkTestnet",
networks: {
zkTestnet: {
url: "https://zksync2-testnet.zksync.dev", // URL of the zkSync network RPC
ethNetwork: "goerli", // Can also be the RPC URL of the Ethereum network (e.g. `https://goerli.infura.io/v3/<API_KEY>`)
zksync: true,
},
},
solidity: {
version: "0.8.17",
},
};
国内环境下还需要在zksolc-setting
中添加一个配置项,这个路径指向 zksync 的 zksolc
编译器。(也可以考虑设置代理,但是我这边代理一直下不了。)
settings: {
"compilerPath": "pathToCompile"
},
同时,从下面的 github 中选取并下载 zksolc
编译器到对应的路径下
如果在主网部署,在 networks
中添加zkMainnet
zkMainnet: {
url: "https://zksync2-mainnet.zksync.io",
ethNetwork: "mainnet",
zksync: true
}
至此,部署合约的环境准备就绪,如果需要切换到主网,可以在配置文件中修改defaultNetwork
字段
在工作目录下创建 contracts
文件夹,然后将写好的合约放入,因为是 zkEVM,所以合约同样是 solidity 语言,不同的只是合约部署的过程不一样
官方文档中的示例合约:
//SPDX-License-Identifier: Unlicensed
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;
}
}
然后在命令行中输入
yarn hardhat compile
在编译完成后会在工作目录下生成两个目录:artifacts-zk 和 cache-zk
然后创建 deploy
文件夹,在这个文件夹下创建 deploy.ts
文件,写入下面的内容,请根据自己合约的需求进行修改
注意:需要部署的合约的文件名务必和合约名一致
import { utils, Wallet } from "zksync-web3";
import * as ethers from "ethers";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { Deployer } from "@matterlabs/hardhat-zksync-deploy";
// An example of a deploy script that will deploy and call a simple contract.
export default async function (hre: HardhatRuntimeEnvironment) {
console.log(`Running deploy script for the Greeter contract`);
// 初始化钱包,这里替换为字符串形式的私钥
const wallet = new Wallet("<WALLET-PRIVATE-KEY>");
// 创建 deployer 对象,并且从abi中初始化合约对象 artifact
const deployer = new Deployer(hre, wallet);
// 这里是官方示例中的名为 Greeter 合约,需要根据具体的合约名字修改
// 注意,合约名字务必和合约文件名一样
const artifact = await deployer.loadArtifact("Greeter");
// 从水龙头请求一些 eth 用来进行部署,如果钱包中有代币,可以直接注释掉这一段代码
const depositAmount = ethers.utils.parseEther("0.001");
const depositHandle = await deployer.zkWallet.deposit({
to: deployer.zkWallet.address,
token: utils.ETH_ADDRESS,
amount: depositAmount,
});
// 等待水龙头发送测试币?
await depositHandle.wait();
// 部署合约,这里的 greeting 是示例合约的构造参数,请根据需要进行修改
const greeting = "Hi there!";
const greeterContract = await deployer.deploy(artifact, [greeting]);
// 输出合约的相关信息
const contractAddress = greeterContract.address;
console.log(`${artifact.contractName} was deployed to ${contractAddress}`);
// 调用已经部署的合约
const greetingFromContract = await greeterContract.greet();
if (greetingFromContract == greeting) {
console.log(`Contract greets us with ${greeting}!`);
} else {
console.error(`Contract said something unexpected: ${greetingFromContract}`);
}
// Edit the greeting of the contract
const newGreeting = "Hey guys";
const setNewGreetingHandle = await greeterContract.setGreeting(newGreeting);
await setNewGreetingHandle.wait();
const newGreetingFromContract = await greeterContract.greet();
if (newGreetingFromContract == newGreeting) {
console.log(`Contract greets us with ${newGreeting}!`);
} else {
console.error(`Contract said something unexpected: ${newGreetingFromContract}`);
}
}
Zksync 官方的演示文档: