Zksync Era: 如何部署智能合约
March 25th, 2023

昨天 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 官方的演示文档:

Subscribe to Deicision
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.
More from Deicision

Skeleton

Skeleton

Skeleton