Developer Docs日本語版
zkSync Japan:WebサイトDocsより
#開発者向けzkSyncの概要
#概要
zkSyncは、Ethereumのスケーリング及びプライバシーエンジンです。現在機能性としては、イーサリアムネットワーク内のETHおよびERC20トークンの低ガス転送を含みます。本ドキュメントは、zkSync開発エコシステムにおけるハイレベルな説明です。
zkSyncはZK Rollupアーキテクチャに基づいて構築されています。ZK RollupはL2スケーリングソリューションであり、全ての資金はメインチェーン上のスマートコントラクトによって保持され、コンピューテーションとストレージはオフチェーンで実行されます。Rollupブロックごとに、状態遷移ゼロ知識証明(SNARK)が生成され、メインチェーンのコントラクトによって検証されます。SNARKには、Rollupブロック内の全ての単一トランザクションの有効性の証明が含まれています。さらに、各ブロックのパブリックデータの更新は、安価なcalldataでメインチェーンネットワーク上に公開されます。
このアーキテクチャにより、以下の保証が得られます:
- Rollupバリデーターは、(サイドチェーンとは異なり)状態を破損させたり資金を盗んだりすることはできない
- (Plasmaとは異なり)データが利用可能であるため、バリデーターが協力を辞めた場合でもユーザーは常にRollupから資金を回収できる
- 妥当性証明のおかげで、ユーザーも他の信頼できるパーティーも、詐欺を防ぐためにRollupブロックを監視するためにオンラインにいる必要はない(ペイメントチャネルやOptimistic Rollupsと異なる)
言い換えれば、ZK Rollupは基盤のL1のセキュリティ保証を厳密に継承しているという事です。
#機能性
まず第一に、zkSyncはスケーリングソリューションとして送金を迅速かつ安価に実行することができます。zkSyncのコア機能のインターフェイスと原理は、このドキュメントのペイメントセクションで説明されています。
第二に、zkSyncはスマートコントラクトに対応しています。2021年を目標に、Rustベースの型安全プログラミング言語であるZincでコントラクトを記述することも、既存のSolidityコードを再利用することも可能になります。コントラクトの相互運用性についてはコントラクトセクションで説明しています。
第三に、zkSyncは取引所フレンドリーです。取引所プロトコルの必須要素であるアトミックスワップが積極的に開発されており、まもなく公開予定です。ご期待ください。
最後に、zkSyncは全ての主要なプラットフォームに対応しています。
SDK セクションのドキュメントをチェックしてzkSyncでの開発を始めましょう。
#zkSyncペイメント
このセクションでは、zkSyncプロトコルの仕組みとその操作方法について説明します。
#目次
#スマートコントラクト
zkSyncは、非常に効率的で安全なチューリング完全な多言語スマートコントラクトの導入を目指しています。
#目次
- Table of contents
- Programming model
- Composability
- Sync VM
- Zinc
- Learning Zinc
- Getting help
- Solidity
- Choosing the framework
- Roadmap
- Testnet
- Mainnet
#プログラミングモデル
zkSyncのスマートコントラクトのプログラミングモデルは、イーサリアムのものを継承しています。
ZincとSolidityの両言語はチューリング完全なので、無制限のループや再帰、任意の長さのベクトルやマップを使用することができます。ローカル変数はスタックやヒープに格納されますが、コントラクトのストレージはグローバルにアクセスされます。コントラクトはインターフェースを介して互いに呼び出し、パブリックストレージフィールドにアクセスできます。
#コンポーザビリティ
zkSyncのスマートコントラクトは、Ethereumのスマートコントラクトと同様に互いに呼び出すことができます。各呼び出しトランザクションツリーは、関係するコントラクトインスタンスの数に関わらずアトミックとなります。
既存のSolidityコードのほぼ変更せずデプロイできるため、どのDeFiプロジェクトもzkSyncに移行することができます。
#Sync VM
Sync VMは、zkSyncスマートコントラクトを実行するための高効率、チューリング完全、SNARKフレンドリーな仮想マシンです。
スマートコントラクトのバイトコードには最先端の最適化が適用され、仮想マシン自体は高負荷に最適化されているため、迅速にトランザクションを実行できます。
このマシンはSNARKフレンドリー、つまり実行トレースがSNARKで証明できるようになっています。ただし、プログラムごとに1回路が必要なわけではありません。代わりに1つの回路を使用することができ、その回路は1回だけ監査する必要があります。
#Zinc
Zincは、zkSyncプラットフォーム上でスマートコントラクトやSNARK回路を開発するための新しいフレームワークです。
既存のZKPフレームワークには、スマートコントラクトに特化した機能がありません。スマートコントラクトは貴重な金融資産を扱うため、セキュリティと安全性が重要となります。そのためSimplicityやLibra’s Moveのような最新のスマートコントラクト言語の設計者は、表現力よりも安全性やコードの正式な検証可能性を重視しています。
Zincは、この2つのギャップを埋めるために作られたものであり、ZKP回路に最適化されたシンプルで信頼性の高いスマートコントラクト言語を提供し、開発者が簡単に習得できるようになっています。
このフレームワークには、スマートコントラクトとゼロ知識証明回路をフラットな学習曲線で開発するために特別に設計された、シンプルでチューリング完全な、安全性を重視した汎用言語が含まれます。構文とセマンティクスは、Rustのものに従っています。
ZincコンパイラーはミドルエンドとバックエンドにLLVMを使用しており、コード最適化のための強力なソリューションを提供しています。
この言語は現在鋭意開発中であり多くの側面が今後改善・変更されるでしょう。しかし、セキュリティやシンプルさなどの基本原則には決して変更は生じません。
#Zincの学習
プログラミング言語Zincには、そのコアとなる原理や慣習を紹介した公式のbookが存在します。
#サポートを受ける
Gitterのチャットルームで質問やサポートを受けることができます。
既存のプロジェクトのzkSyncへの移行を考えており、サポートが必要な場合はhello@matter-labs.io までメールをお送りください。
#Solidity
Solidityは、巨大なコードベースと多数のDeFiプロジェクトを持つ汎用言語で、世界中の何千人ものブロックチェーン開発者に採用されています。
大半のSolidityプロジェクトはほぼ変更なくデプロイ可能ですが、いくつかの機能が禁止される可能性が高いため、コードの互換性を保つために以下を省略する必要があります:
- メモリアクセスを行うASMブロック
- オーバーフローによる計算の容易化
- ABIコントラクトコール
- 未定義の動作の一般的なケース
また、SolidityからZincへの移行を容易にするために、SolidityからZincへのトランスパイラを開発しています。
#フレームワークの選択
#ロードマップ
#Testnet
zkSyncのスマートコントラクトのテストネットがライブになりました!Curve Financeが最初のdappとして2020年10月にローンチしました。イントロ記事をチェックしてみてください。
また、Zandboxサーバーを使って任意のスマートコントラクトを自由にテストすることができます。このチュートリアルでは、Rinkebyテストネットにスマートコントラクトをデプロイする方法を説明しています。
#Mainnet
zkSyncスマートコントラクトが2021年にメインネット化し、ZincとSolidityの両方がローンチ時にサポートされます。
#zkSync 1.xでのNFT
zkSync 1.xでのNFTのサポートを開始しました。機能としてはNFTのミント、トランスファー、アトミックスワップなどがあります。また、レイヤー1へのNFTの出金も可能になります。
現在Rinkeby-betaとRopsten-betaでテストネットが行われています。
ここではzkSync 1.xにNFTがどのように実装されているかを明示し、プロジェクトにNFTを統合するためのチュートリアルを提供します。
#概要
NFTアドレスは、以下のようにNFTコンテンツとメタデータをエンコードします:
これにより、2つの不変性が暗号で保証されます:
- NFTアドレスは、作成者やNFTのシリアル番号、そのコンテンツのハッシュに対するユニークなコミットメントとして機能します
- NFTアドレスは誰にもコントロールされず、メインネット上にスマートコントラクトコードを持つこともできません
注意: zkSync 1.xでは、複数のNFTを同じコンテンツハッシュでミントすることができます。
#設定方法
チュートリアルを始める前にGetting Startedガイドをお読みください:
# zkSync@beta libraryのインストール
#Rinkeby-beta テストネットへの接続
このチュートリアルでは、Rinkeby-beta テストネットに接続してみましょう。Ropsten-betaでもOKです。
#Mint
NFTをミントするために引数付きの新しいオペコードMINT_NFT
を導入します:
- クリエイターアカウントID
- コンテンツハッシュ
- 受信者アカウントID
recipient_account_id
を渡すことで、クリエーターが自分自身にミントするか、他の人に直接ミントするかを選択できるようになります。
#ユニーク性の確保
NFTトークンIDのユニーク性を確保する為に、zkSyncのバランスツリーの最後のアカウントを使用してトークンIDを追跡します。このアカウント(SpecialNFTAccountとします)は、最新のミントのトークンIDを表すSPECIAL_NFT_TOKENの残高を持ちます。
NFTトークンのアドレスのユニーク性を確保する為に、アドレスを生成するハッシュの入力としてserial_id
をリコールします。クリエイターのアカウントにはSPECIAL_NFT_TOKEN
の残高があり、これはserial_id
つまりクリエイターがミントしたNFT数を表します。
zkSyncのサーバーは、NFTトークンのアドレスとトークンIDのマッピングを保持します。
#トランザクション手数料の計算
NFTをミントする為のトランザクション手数料を計算するには、Provider
クラスのgetTransactionFee
メソッドを使用します。
Signature
例:
#NFTのミント
zksync@betaバージョンで利用可能になったWallet
クラスからmintNFT
関数を呼び出すことで、NFTをミント化することができます。
Signature
例:
#Get a Receipt
To get a receipt for the minted NFT:
#NFTの表示
NFTがミントされた後、NFTにはコミットと検証という2つの状態があります。NFTは、ロールアップブロックに含まれている場合はコミットされ、そのブロックに対してゼロナレッジプルーフが生成され、ロールアップブロックのルートハッシュがEthereumメインネット上のスマートコントラクトに含まれている場合は検証されます。
アカウントのNFTを表示するには以下の方法があります:
Wallet
クラスのgetNFT
関数も役に立つでしょう。
Signature
#転送
ユーザーは既存のアカウントにNFTを転送したり、まだzkSyncアカウントを登録していないアドレスに転送することができます。TRANSFER
とTRANSFER_TO_NEW
のオペコードは同じように動作します。
NFTは、そのミントトランザクションを持つブロックが検証された後にのみ転送できます。つまり、新しく作成されたNFTは、転送できるようになるまで数時間待たなければならない可能性があります。これは最初の送金にのみ適用され、その後の送金はすべて制限なく行うことが可能です。
NFTを送金するにはsyncTransferNFT
関数を呼び出します:
syncTransferNFT
関数は、ボンネット内でバッチ処理されたトランザクションとして動作するため、最初のハンドルがNFT送金、2番目のハンドルが手数料となるトランザクションの配列を返します。
#領収書の発行
振込のレシートを発行するには:
#スワップ
スワップ機能は、あるNFTと別のNFTのアトミックスワップに使われます:
#NFTのスワップ
2つのNFTを交換するには、それぞれが売るNFTと買うNFTのNFT IDを指定して注文を出します。
getOrder
メソッドを使用します:
注:NFTからNFTへのスワップを行う場合、比率は常に 1 に設定されます
2つの注文がサインされた後、syncSwap
メソッドを呼び出すことで誰でもスワップを開始することができます:
レシートを入手:
#NFTの売買
ファンジブルトークンのNFTを売買するには、各当事者がNFT IDと送出/受領するトークン名を指定して注文に署名します。この例では、比率のパラメータに特に注意してください。利用可能なトークンとそのシンボルのリストはエクスプローラーで閲覧できます。
#Layer 1への出金
レイヤー1への出勤には3人のアクターが必要となります:
本ガイドでは、通常出金と緊急出金の2種類の出金方法を紹介し、それぞれの出金方法がどのような状況で使用されるのかを説明します。また、zkSyncとL1の間のNFTトークンブリッジのアーキテクチャと、プロトコルがL1に独自のNFTファクトリー・コントラクトを実装する場合に必要なものについても説明します。
#NFTの出金
通常ではレイヤー2のオペレーションである withdrawNFT
を出金に使用します。
Signature
レシートの入手:
#緊急時の出金
検閲が行われた場合、ユーザーは緊急に出金を要請することができます。注:これはレイヤー1の操作でありfullExit mechanismに類似しています。
Signature
#ファクトリーとzkSyncスマートコントラクトの相互作用
独自のミントコントラクトを実装したくないプロジェクトのために、L1でのNFTのミントを処理するデフォルトのファクトリーコントラクトを用意しています。独自のミントコントラクトを持つプロジェクトは、1つのミント関数mintNFTFromZkSync
を実装するだけで済みます。
zkSyncガバナンスコントラクトは、ファクトリーコントラクトの為にL2上の信頼されたミンターとしてクリエイターを登録する関数registerFactory
を実装します。
出金には、ユーザーはtoken_idを使ってwithdrawNFT()
を呼び出す必要があります。zkSyncスマートコントラクトは所有権を確認し、トークンをL2にバーンして、作成者に対応するFactoryでmintNFTFromZkSync
を呼び出します。
#Factoryの登録
Factoryを登録する為に、クリエイターはfactory_address
と creator_address
のデータを使って以下のメッセージに署名します。
Factoryコントラクトは、署名でzkSync L1スマートコントラクトのregisterFactory
を呼び出します。
zkSyncスマートコントラクトは署名を検証し、factory_address
とcreator_address
を含むイベントを発行します。
スワップと指値注文
#アトミックスワップ
アトミックスワップでは、既存のzkSyncアカウントと安全かつ安価に資金を交換することができます。
スワップを成功させる為には3つのステップが必要です:
#注文への署名
注文を出すには、以下の情報が必要です:
比率とは、トークンを交換する際の比率を表す15バイトの整数です。
注文に署名するにはWallet
のgetOrder
メソッドを使います:
注文には以下も含まれます:
recipient
— スワップの結果を転送する既存のアカウントのアドレス(スワップと転送を行う場合)。デフォルトは self です。validFrom
およびvalidUntil
Unix のタイムスタンプで、スワップ付きのブロックを処理できる時間帯を制限します。- スワップに使用される
nonce
#スワップの提出
以下の条件を満たせば、誰でも2つの注文をスワップに出すことができます:
- 注文のトークンが一致していること:
orderA
がtokenA -> tokenB
を指定している場合orderB
はtokenB -> tokenA
を指定する必要があります - 注文内の比率が一致している:
1/orderB.ratio <= orderA.amount/orderB.amount <= orderA.ratio
- 注文に受信者がいる場合、そのアカウントがzkSyncに存在していること
手数料は提出者が負担し、負担するトークンを指定する必要があります。スワップが実行されると、スワップするアカウントと送信者の両方でnonceがインクリメントされます。スワップが片方のアカウントから送信された場合、nonceは一度だけ増加します。
送信されていないスワップをキャンセルしたい場合は、nonceをインクリメントするだけです(例:ゼロトランスファーの送信)
スワップを送信するにはWallet
のsyncSwap
メソッドを使用します:
#指値注文
指値注文とは、あるトークンと別のトークンを一定の価格で交換する方法です。指値注文は、主に信頼性が高くスケーラブルな交換サービスを提供したい他のプラットフォームで使用されることを想定しています。
警告:あるトークンに対して指値注文が成立すると、残高全体が(指定された比率で)別のトークンに交換される可能性があることを意味します。交換できる量を制限するには、特別なトレードアカウントを使用する以外に方法はありません。
#トレードアカウントディング口座
トレードアカウントとは、指値注文を行う為のアカウントのことです。これは、ユーザーが交換したい特定のトークンの量を制限するための機能です。
これを行うためには、ユーザーは以下のことをしなければなりません:
この方法では、指値注文は最大でもトレードアカウントに送金した金額を交換します。メインアカウントの残りの残高はそのままになります。
#指値注文のサイン
指値注文をサインするにはWallet
のgetLimitOrder
メソッドを使用します。
#指値注文の充足
指値注文自体は、スワップ運用の半分に過ぎません。注文を成立させるためには、以下の条件を満たす必要があります:
スワップ取引の際には、充足される金額を指定してください。指値注文は部分的に満たされる為、金額は実際の残高とは異なっていても構いませんが、オーダーで指定された比率と一致している必要があります。詳細は例をご参照ください。
#指値注文のマッチングに関する注意事項
アトミックスワップの実行は、スワップしたい相手と署名済みの注文メッセージを共有するだけで簡単にできます。
一方、指値注文のマッチングは、何らかのマッチングエンジンを用いて既存のユーザーベースを持つプラットフォームで行うべきでしょう。
zkSyncは可能な限り汎用的であることを目指しているため、マッチングエンジンの作成は考慮されていません。
#提案
トレードアカウントはCREATE2アカウントとして作成することができます。この方法には以下のようなメリットがあります:
- CREATE2アカウントに署名鍵を設定するコストが安い
- CREATE2のSalt引数を利用して、特定のメインアカウントに対するトレードアカウントのアドレスを決定論的に生成することができる
- 必要に応じて、同じL2秘密鍵を全てのトレードアカウントとメインアカウントに使用することができます。これには複数のリスクがありますが(1つのアカウントを侵害することは、すべてのアカウントを侵害することになります)鍵の管理が不便な状況も存在します。
プラットフォームがトレードアカウントにCREATE2を使用する場合、アドレスの計算に使用するコントラクトバイトコードを選択する必要があります。このコントラクトはオープンソースで、完全な出入力機能を備えている必要があります。なぜなら、検閲が行われた場合、ユーザーは資金を救出するためにコントラクトを使用しなければならないからです。
また、注文が成立したりキャンセルされたトレードアカウントの再利用を提案します。これにより署名鍵を再度設定する必要がなくなります。
#実例
ここでは、注文で指定した比率がアカウントの残高にどのように影響するかを例示します。
walletA
は、各wBTC(またはそれ以上)に対して2.5ETHの獲得が期待されますwalletB
は、1つのETH(またはそれ以上)に対して0.25 wBTCの獲得が期待されます
どちらの比率でも(またはその中間でも)比率は両立します。
orderB
の比率では、walletA
は1wBTCあたり4ETHを得ることができ、これは期待以上のものですorderA
の比率では、walletB
はETHあたり0.4wBTCを得ることができ、これは期待以上のものです
では、実際にスワップを申し込んで、その中間の比率-wBTCあたり3ETHを選んでみましょう:
これによりwalletA
の100 wBTCとwalletB
の300 ETHが交換されます。詳しい情報は下の表をご覧ください。