# Zksync Era: 如何部署智能合约

By [Deicision](https://paragraph.com/@deicision) · 2023-03-25

---

昨天 Zksync 上线了 Era 主网，在测试的时候想部署合约试试，结果发现直接使用 Remix 无法部署合约

查阅了文档才发现 Zksync Era 和 EVM 部署合约的流程不一样，甚至有自己的一套 sol 编译方法

[https://era.zksync.io/docs/](https://era.zksync.io/docs/)

先试了用 python 来部署发现不太行，python-sdk 和节点的 RPC 似乎还没有对齐，所以在使用的时候会报错。最后是用 Hardhat 部署上去了，踩坑一晚上，社区也还没有相关的提问所以分享一下。

环境准备
----

hardhat 需要在 yarn 中配置，需要预先配置 yarn 环境

[https://yarnpkg.com/getting-started/install](https://yarnpkg.com/getting-started/install)

然后创建一个目录作为工作目录，并且使用 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` 编译器到对应的路径下

[https://github.com/matter-labs/zksolc-bin](https://github.com/matter-labs/zksolc-bin)

如果在主网部署，在 `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 官方的演示文档：

[https://era.zksync.io/docs/api/hardhat/getting-started.html#write-and-deploy-a-contract](https://era.zksync.io/docs/api/hardhat/getting-started.html#write-and-deploy-a-contract)

---

*Originally published on [Deicision](https://paragraph.com/@deicision/zksync-era)*
