2023.03.17
zkSync Era(2.0)でNFTコントラクトを動かしてみよう〜zkロールアップとは?〜
こんにちは。次世代システム研究室のL.C.A.です。
はじめに
イーサリアムのレイアー2(L2)zkRollupソリューションzkSync は最近(2023/2/16)、zkSync 2.0(zkSync Era)のメインネットは『Fair Onboarding Alpha』段階に入ったと発表しました。これから、事前に登録したプロジェクトはzkSync Eraメインネットにてスマートコントラクトのデプロイやテストができるようになります。L2のOptimism Rollup エコシステムの活発さと比べ、zkRollup はより高いセキュリティとスケーラビリティがあるものの、開発技術のハードルが高いため、発展するスピードは比較的遅いです。ただし、最近zkEVM技術は大きな進展があるため、将来的にはzkRollupの注目度はOptimism Rollup より高くなると考えています。
この記事では、zkRollup、zkSync Eraの簡単なご紹介のほか、zkSync Era にてErc721 NFT コントラクトを動かしてみようと思います。
TL;DR
- zkRollups はOptimistic Rollups より高いスケーラビリティとセキュリティ( L1 と同等)を備えているが、開発の難易度はOptimistic Rollups より高く、より高いコンピューティングパワーを消費する。
- zkSync は zkRollupのソリューションであり、EVM と高い互換性を持ち、スマートコントラクトはイーサリアムの既存言語Solidity または Vyper で書かれる。
- 現在主流となっているイーサリアム開発フレームワーク Hardhat と zkSync が提供する Hardhat SDK を使用し、zkSync Era Goerilテストネットに Solidity Erc721 コントラクトを動かしてみた。
Rollup とは
Rollup は Ethereum L2 のソリューションの一つです。そのコンセプトは、TX(トランザクション)計算をoff-chain(L1の外部)で実行し、ストレージはon-chain(L1の内部)にする(複数の TX を抽出し、最終的に圧縮された複数 TX を L1 に提出する)というものです。
また、Rollupが L2 で実行される際、L1 にて資金をロックする必要があり、資金に関連するトランザクションは処理のために L2 に移動されます。これにより、 L1 のTXの処理時間とコストを効果的に削減できます。
Rollupの分類
現在、イーサリアムのRollupは主にOptimistic RollupとzkRollupの2つに分類されます。以下の通り、両者の最大の違いはバッチTXをL1に提出した際の処理方法です。
Optimistic Rollup
楽観という意味であり、全部のTXのデータは正当なものだという楽観的な前提に基づいて、L2からL1にRollupする際、証明を持たずにTXデータをL1に提出します。
証明の代わりに、L1へ資産を戻す前に約7日間のfraud proofsという詐欺証明の提出の仕組みを設けます。不正当なTXが見つかった場合、TXロールアップオペレーターは罰金を科され、報告者には報酬が与えられます。
メリット
- EVMへの互換性が高い
- 開発や仕組みがzkRollupより簡単なため、エコシステムの発展はzkRollupより早い
デメリット
- L1へ資産の戻り時間が遅い(7日間)
- Fault Proofの期間中に L1からL2のお金を引き出せない
- スケーラビリティはzkRollupより低く、TPSの限界は1588程度(Arbitrum、Optimism)
zkRollup
「ゼロ知識証明(Zero Knowledge)」という暗号化手法で、全てのTXの署名をゼロ知識証明を使って ZKP(ゼロ知識証明) データを生成し、最後に圧縮されたTXとZKPデータをひとまとめにしてL1 に提出します。
メリット
- L1へ資産の戻り時間が早い(数十分)
- ZKPにより、TXの正当性はすぐに検証可能
- スケーラビリティが高く、TPSの限界は12000程度 (VISAは24,000tpsほど)
デメリット
- EVM(OP-Code)への互換性を高くするため開発が難しい
- 開発の難易度が高いため、現在のエコシステムは比較的健全ではない
- ゼロ知識証明の計算量は多い、ハードウェアの要件が高い
- 既存例:zkSync、Starknet

出典:https://medium.com/taipei-ethereum-meetup/blockchain-layer2-rollup-74658b9d2498
zkSync Era(2.0)概要
zkSync Era(2.0)はzkRollupのソリューションであり、zkSync lite(1.0)より高いスケーラビリティや安全性を持ち、スマートコントラクトもデプロイできます。また、EVM と高い互換性を持ち、スマートコントラクトはイーサリアムの既存言語Solidityまたは Vyperで書かれます。zkSync が利用しているゼロ知識証明手法はzkSNARKであり、他の有名な手法zkSTARKと比較すると、証明サイズは比較的小さいものの、量子コンピューター耐性の懸念の観点において懸念があるとされています。
zkSync Eraの特徴は下記となります。
- Solidity 0.8.x までのスマートコントラクトをサポート
- 安全性はL1と同等
- zkEVMはEVMと高い互換性と等価性
- L1 → L2 smart contract messagingを提供
- Account Abstraction(AA)をサポート


Hello zkSync Era!
今回は現在主流になっているイーサリアム開発フレームワーク Hardhat と zkSync が提供する Hardhat SDK を使用し、zkSync Era Goerilテストネットにて Solidity Erc721 コントラクトのデプロイやNFTのMINTを試してみたいと思います。
それでは、早速実装してみましょう!
環境構築
事前確認
- yarnインストール済み
- chromeブラウザにてmetamask walletをインストール済み
プロジェクトの初期化
- オフィシャルのガイドに沿って、
zkNFT
フォルダーを作成し、必要なnode moduleをインストールします
$ mkdir zkNFT-example $ cd zkNFT-example $ yarn init -y
zkNFT
フォルダーの中package.json
ファイルを配置します
{ "name": "greeter-example", "version": "1.0.0", "main": "index.js", "license": "MIT", "devDependencies": { "@matterlabs/hardhat-zksync-deploy": "^0.6.2", "@matterlabs/hardhat-zksync-solc": "^0.3.14", "@matterlabs/hardhat-zksync-verify": "^0.1.3", "@nomiclabs/hardhat-etherscan": "^3.1.7", "ethers": "^5.7.2", "hardhat": "^2.13.0", "@openzeppelin/contracts": "^4.1.0", "ts-node": "^10.9.1", "typescript": "^4.9.5", "zksync-web3": "^0.13.1" } }
node module
をインストールします
$ yarn install
hardhat.config.ts
を作成し、下記のコードを貼り付けます
import "@matterlabs/hardhat-zksync-deploy"; import "@matterlabs/hardhat-zksync-solc"; import "@matterlabs/hardhat-zksync-verify"; module.exports = { zksolc: { version: "1.3.1", compilerSource: "binary", settings: {}, }, defaultNetwork: "zkSyncTestnet", networks: { zkSyncTestnet: { url: "https://zksync2-testnet.zksync.dev", ethNetwork: "goerli", // Can also be the RPC URL of the network (e.g. `https://goerli.infura.io/v3/`) zksync: true, // Verification endpoint for Goerli verifyURL: "https://zksync2-testnet-explorer.zksync.dev/contract_verification", }, }, solidity: { version: "0.8.17", }, };
contracts/zkNFT.sol
ファイルを作成し、下記のERC721 Solidityコードを貼り付けます。
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; contract zkNFT is ERC721 { using Counters for Counters.Counter; Counters.Counter private _tokenIds; constructor() ERC721("zkNFT", "ZKNFT") {} function mintNft(address receiver) external returns (uint256) { _tokenIds.increment(); uint256 newNftTokenId = _tokenIds.current(); _mint(receiver, newNftTokenId); return newNftTokenId; } function _baseURI() internal pure override returns (string memory) { return "https://example.com/nft/"; } }
- Solidityコードをコンパイルします
$ yarn hardhat compile
デプロイの準備
- 下記のFaucetからzkSyncテストネットのETHを取得できます
- また、ブリッジでL1のGoerliテストネットからETHをSwapできます
- Metamaskにて、テストネットの接続情報を追加します
- Network Name:
zkSync Era Testnet
- New RPC URL:
https://zksync2-testnet.zksync.dev
- Chain ID:
280
- Currency Symbol:
ETH
- Block Explorer URL:
https://goerli.explorer.zksync.io/
- WebSocket URL:
wss://zksync2-testnet.zksync.dev/ws
- Network Name:

deploy/deploy.ts
を作成し、下記のコードを貼り付けます-
<プライベートキー>
にてアカウントのプライベートキーを引き換えましょう
-
import { Wallet, utils } 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 zkNFT contract`); // Initialize the wallet. const wallet = new Wallet( "<プライベートキー>" ); // Create deployer object and load the artifact of the contract you want to deploy. const deployer = new Deployer(hre, wallet); const artifact = await deployer.loadArtifact("zkNFT"); // Estimate contract deployment fee const deploymentFee = await deployer.estimateDeployFee(artifact, []); // Deploy this contract. The returned object will be of a `Contract` type, similarly to ones in `ethers`. const parsedFee = ethers.utils.formatEther(deploymentFee.toString()); console.log(`The deployment is estimated to cost ${parsedFee} ETH`); const zkNFTContract = await deployer.deploy(artifact, []); //obtain the Constructor Arguments console.log("constructor args:" + zkNFTContract.interface.encodeDeploy([])); // Show the contract info. const contractAddress = zkNFTContract.address; console.log(`${artifact.contractName} was deployed to ${contractAddress}`); }
- アカウントがzkSyncテストネットのETHを取得してから、コントラクトをデプロイします
$ yarn hardhat deploy-zksync The deployment is estimated to cost 0.0008228305 ETH constructor args:0x zkNFT was deployed to 0x3a1eE4EA4fC9efBCeCF0d31468C13d54Ad6F95B5
- デプロイしたコントラクトはzkSync Era Block Explorerにて確認できます

-
zkSync Era Block ExplorerにてデプロイしたコントラクトをVerifyできます
$ hardhat verify --network <network> <contract address> 例: $ yarn hardhat verify --network zkSyncTestnet 0x3a1eE4EA4fC9efBCeCF0d31468C13d54Ad6F95B5 Successfully compiled 12 Solidity files Your verification ID is: 3617 Contract successfully verified on zkSync block explorer! ✨ Done in 14.55s.
- verifyした後のコントラクトは下記となります

Connect Metamask
のボタンを押してMetamaskのアカウントと接続してからMINTしてみます

- MINT手数料もとても低いことが確認できます(0.000242406ETH)

- NFT
Symbol
やtokenURI
が確認できます

-
MINTしたNFTトークンはMint Squreという NFTマーケットプレイスで確認できます(作成したNFTのbaseurlはexampleなので、画像には反映されません)

まとめ
この記事では、イーサリアム L2 ソリューション zkRollupおよびzkSync Eraを簡単にご紹介し、zkSync Era テストネットで SolidityのERC721 コントラクトも実装してみました。
この実装により、zkSync EraでのMINT NFT の手数料は、L1のイーサリアムの 0.01-0.05 ETH よりはるかに低いことがわかりました。また、zkEVMはEVMとの高い互換性などの特徴により、zkRollup の発展性はとても期待できると思います。
次世代システム研究室では、グループ全体のインテグレーションを支援してくれるアーキテクトを募集しています。インフラ設計、構築経験者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ募集職種一覧からご応募をお願いします。
皆さんのご応募をお待ちしています。
参考
グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。
Follow @GMO_RD