# ZetaChainのオムニチェーンスマートコントラクトとクロスチェーンメッセージング

By [hashigo](https://paragraph.com/@hashigo) · 2022-11-27

---

1\. ZetaChainについて
=================

ZetaChainは、クロスチェーン間のメッセージングやオムニチェーンコントラクトを実現するL1のブロックチェーンです。

ホワイトペーパーの日本語訳（非公式）はこちら：

[https://hashigocchi.notion.site/ZetaChain-3c11c23b69df4bf881e2928c33a0d868](https://hashigocchi.notion.site/ZetaChain-3c11c23b69df4bf881e2928c33a0d868)

また、ホワイトペーパーの要約も用意してあります：

[https://mirror.xyz/hashigo.eth/5BL0waxhAABJQORAsDLEkn5qbFa5lYWKEnZ8-l\_inDs](https://mirror.xyz/hashigo.eth/5BL0waxhAABJQORAsDLEkn5qbFa5lYWKEnZ8-l_inDs)

**本記事を読む前に、以上の内容に目を通すことを推奨します。**

2\. ZetaChainのアーキテクチャ（おさらい）\[1\]
================================

2.1 概要
------

ZetaChainはCosmos SDKとTendermint PBFTコンセンサスエンジン上に構築されたProof of Stake (PoS)ブロックチェーンです。よって、ZetaChainは高速なブロック時間（〜5秒）とインスタントファイナリティを享受しています。Tendermint PBFTコンセンサスエンジンは、実運用で300ノードまで拡張可能であることが示されています。将来的にBLSしきい値署名によるアップグレードで、その数は1000以上まで増える可能性があります。ZetaChain上のトランザクションのスループットは、効率的なTendermintコンセンサスプロトコルにより、100TPSに達する可能性があります。

ZetaChainのアーキテクチャは、しばしばバリデータと呼ばれるノードの分散ネットワークで構成されています。バリデータは、関連する外部の状態とイベントに関するコンセンサスに達する分散型オブザーバとして機能し、また、分散キー署名によって外部のチェーン状態を更新することができます。ZetaChainは、分散型（単一障害点なし、トラストレス、パーミッションレス）、透明、かつ効率的な方法で、これらの機能を達成します。各バリデータ内に含まれるのは、ZetaCoreとZetaClientです。ZetaCoreはブロックチェーンを生成し、複製されたステートマシンを維持する責任を負います。バリデータのオペレータは、このアーキテクチャの異なるコンポーネントを実行します（下記参照）。

ZetaChainのアーキテクチャ\[1\]

2.2 バリデータ
---------

バリデータは3つの異なる役割で構成されています。Basicバリデータ、オブザーバ、TSS署名者です。バリデータは、トランザクションを処理し、ネットワークを安全に保つというサービスの対価として、トランザクションからの手数料と報酬が分配され、受け取ります。オブザーバーとTSS署名者は、セキュリティや掛け金の要件が異なるため、Basicバリデーターとは別の規模になります。

### 2.2.1 **Basicバリデータ**

ZetaChainは、部分的な同期ビザンチンフォールトトレラント（BFT）コンセンサスアルゴリズムであるTendermintコンセンサスプロトコルを使用します。各バリデータ・ノードは、拘束/委任されたステーキングコイン（ZETA）に比例した投票権により、ブロックの提案に投票することができます。各バリデーターはコンセンサス公開鍵によって識別されます。バリデータは常にオンラインである必要があり、常に成長し続けるブロック生成に参加します。バリデータはそのサービスの対価として、ブロック報酬と取引手数料を受け取ります。

### 2.2.2 **オブザーバ**

ZetaChainのコンセンサスにとって重要なもう一つの参加者は、外部のチェーンイベントと状態についてコンセンサスを得るオブザーバです。オブザーバは、外部チェーンの完全なノードを介して、特定のアドレスで特定の関連する取引、イベント、状態について、外部接続チェーンを監視します。オブザーバはシーケンサと検証者の2つの役割に分かれます。シーケンサは関連する外部のトランザクション/イベント/状態を発見して検証者に報告し、検証者はZetaChainを検証して投票し、コンセンサスを得ます。このシステムには、少なくとも1人のシーケンサと複数の検証者が必要です。シーケンサはトラストされる必要はありませんが、少なくとも1つの正直なシーケンサが必要です。

### 2.2.3 **TSS署名者**

ZetaChainは、外部チェーンとの認証された相互作用のために標準的なECDSA/EdDSAキーをまとめて保持します。鍵は、それらの超多数だけがZetaChainを代表して署名できるような方法で、複数の署名者の間で分配されます。重要なことは、いかなる時も、単一のエンティティまたはノードのごく一部が、ZetaChainを代表して外部チェーン上でメッセージに署名できることを確実にすることです。ZetaChainシステムは、経済的安全を確保するために、担保つきのステークと正/負のインセンティブを使用します。

2.3 Zeta EVM (zEVM)とオムニチェーンスマートコントラクト
-------------------------------------

Zeta EVM（zEVM）は、ZetaChainのコアブロックチェーン上に構築されたオムニチェーンスマートコントラクトをデプロイして使用できるEthereum互換の仮想マシンです。zEVM上のコントラクトはZetaChainの相互運用性レイヤーに接続されており、外部チェーン上のアセットをあたかも単一のチェーン上にあるかのようにオーケストレーションすることが可能です。

2.4 クロスチェーンメッセージング
------------------

ZetaChainの相互運用性アーキテクチャを通じて、接続されたチェーン上の既存のスマートコントラクトに3つの機能を実装することにより、任意のチェーンから任意のチェーンへメッセージ（データと価値）を送信することができます。ZetaChainのメッセージングシステムは、ZETAコインのワンウェイペグ機構により、新たなブリッジやラップアセットを必要としないネイティブな価値転送を可能にします。ガス代などの手数料はすべてユーザーが一括して支払うことができるため、開発者はシームレスなUXを提供することができます。また、メッセージングは、トランザクションの失敗時の復帰処理をサポートするため、より予測可能で直感的な開発者体験を生み出します。

3\. オムニチェーンスマートコントラクトとメッセージング
=============================

3.1 ZetaChainのメッセージングとスマートコントラクトの違い\[2\]
----------------------------------------

メッセージングは、スマートコントラクトがZetaChain上であろうと外部チェーン上であろうと、開発者が、スマートコントラクト間でデータと値を送信することを可能にします。1つは、外部チェーン上のスマートコントラクトを展開し、LayerZeroのような他の相互運用性メッセージングプロトコルと同様の方法でZetaChainを介してそれらの間でメッセージを渡すだけですが、ZetaChainの相互運用性スマートコントラクトは、開発者が単一の場所内のオムニチェーンロジックを維持し、オーバーヘッドを減らし、BitcoinやDogecoinなどの非スマートコントラクトチェーンでさえ制御できるスマートコントラクトロジックを許可します。

3.2 オムニチェーンスマートコントラクトとメッセージングの比較\[3\]
-------------------------------------

あなたのアイデアをもとに開発を始めるとき、あなたはどのように自分のdAppを構築するべきか疑問に思うかもしれません。ここでは、アプリケーションのアーキテクチャを決定するのに役立つ考慮事項をいくつか紹介します。

### 3.2.1 アーキテクチャの決定

古いソリューションであるメッセージパッシングでは、別のブロックチェーンにメッセージを転送するためのリレーとしてのみZetaChainが使用されます（例：Ethereum → BSCなど）。dAppは、接続された各チェーン上に少なくとも1つのコントラクトをデプロイします。dAppのステートとロジックは、非同期メッセージで接続されたこれらのチェーン上のすべてのコントラクトに散在しています。これは、一方向の非同期ロジックやエフェクトのみを必要とし、統一されたステートを必要としない、または恩恵を受けない特定のアプリケーションにとっては理にかなっています。

オムニチェーンスマートコントラクトとZRC-20トークンを使用した新しいアーキテクチャは、非常に異なるトポロジーを持ちます：dAppにはzEVM上の1つのコントラクトのみが必要で、外部のチェーンにはdAppコントラクトは必要ありません。zEVMはZRC-20コントラクトを経由して外部チェーン上のコインを管理します。ZRC-20コントラクトについては次の章で説明します。

dAppは、以下の考慮事項に基づき、これらのソリューションのいずれかを活用することができます。

### 3.2.2 dAppの複雑さ

メッセージングを使用する場合、異なるチェーン上の多くのコントラクトにメッセージと状態同期をブロードキャストする必要があり、これは実質的により多くの攻撃対象とガス代（各メッセージは追加のガス支払いを必要とし、完全な状態同期を維持するために送信しなければならないメッセージ数はスケールします）につながる可能性があるからです。

### 3.2.3 既存のEVMコントラクトの上での構築

Uniswap V2/V3、Curve、Aave、Compoundなど、Ethereum上で監査とテストが行われた共通のアプリケーションは、ZetaChainで簡単に展開でき、その上に構築されることができます。ZRC-20との互換性を追加することでこれらのアプリケーションを拡張することはできますが、それらの変更は最小限であり、ロジックの大部分は同じままで、ユーザーはEthereum上で行うのと同じようにシングルステップのトランザクションでこれらのアプリケーションとやり取りすることができます。一方、メッセージングでは、多くの状況（特に複雑なもの）で、開発者は「車輪を再発明する」必要があります。つまり、まったく別の非同期メッセージングおよびステートシンクシステムでロジックを作り直す必要があり、メッセージングでは既存のアプリケーションを同じように活用することができません。

### 3.2.4 非スマートコントラクトチェーンのサポート

ZRC-20はBitcoin/Algorand/Cardano/XRPを簡単にサポートできますが、スワップ、融資などのアプリケーションのための汎用スマートコントラクトをサポートする能力はなく、非効率です。メッセージングには、接続されたチェーン上のスマートコントラクトが必要なため、これらのチェーンではメッセージングが機能しません。

### 3.2.5 外部におけるガス代

ZRC-20は、外部チェーンとのやり取りがファンジブルなコインに限定されているため、多くのユースケースでメッセージパッシングよりも大幅にガスコストが低くなる可能性があります。（ETH/BNB/MATICの標準Transferには21kガス、ERC20トークンの移動には約60kガスのコストがかかります; 外部チェーン上でロジック/状態がないことはガスコストを大幅に削減します）。メッセージパッシングは本質的に送信元/送信先のチェーンでメッセージデータを処理する必要があり、検証作業等のために追加のガスコストがかかります。

### 3.2.6 流動性の一元化

オムニチェーンスマートコントラクトでは、ネイティブアセットの流動性を直接ペアリングし、互いに交換することができます。これは、ネイティブアセットを取引するためのステップを最小限にし（1ステップ）、ブリッジやラッピングのステップや複雑なメッセージの送信を伴いません。例えば、統一されたプールを介して、Ethereum上のETHとPolygon上のUSDCを1ステップで直接取引することができます。メッセージを使えば、既存のチェーン上のUniswapプールのような既存の流動性を活用し、ZetaChainを通じてZETAを焼却/造幣することで取引することができます。このアプローチはより複雑（より多くのトランザクションを含むため、ガス代がかかる）かもしれませんが、ZetaChainのエコシステム内の流動性に依存しません。オムニチェーンスマートコントラクトとメッセージングの両方が統一された流動性へのアプローチを提供する一方で、彼のシステム要件に基づいて選択するのは開発者次第です。

### 3.2.7 例外処理

ZRC-20/zEVMでは、トランザクションが処理されると同時に、外部とのやり取りが標準のERC-20/コントラクトとのやり取り（成功）、またはコントラクトとのやり取りなし（失敗）に限定されるため、例外/復帰処理がはるかにシンプルになります。それに比べ、メッセージングでは復帰処理をサポートしていますが、dApp（とユーザー）はエラーを首を長くして待ち、非同期/イベント駆動の方法で処理しなければなりません。

3.3 メッセージングとzEVMスマートコントラクトの比較例\[3\]
-----------------------------------

これらの2つの大まかな例は、オムニチェーンスマートコントラクトで構築する場合とメッセージングで構築する場合の違いを示しています。

### 3.3.1 Curve/マルチアセットプールの例

まず、Curveを検証してみましょう。Bitcoin上のBTC、Polygon上のMATIC、Ethereum上のETHでEthereum上にCurveプールを作成することを想像してください。

1.  BTCとMATICをEthereumにブリッジする必要があります（新しいラップされたアセットwBTCとwMATICを作成するか、BTCとMATICを表すような、ブリッジvaultに依存する何らかのネイティブ/既存アセットとのスワップを試みる必要があります）。
    
2.  これらのアセットのために作成されたプールに入金します。
    
3.  流動性を引き出すには、プールから引き出して、これらのラップされたバージョンのアセットを受け取る必要があります。
    
4.  それらを一つ一つ、PolygonとBitcoinに戻すブリッジによってアンラップします。
    
5.  誰かがこのプールを通してスワップする場合、その人はラップされたアセットを受け取り、その後、最終的にそれらを送信したい場所にアセットをアンラップ/ブリッジします。
    

その代わり、BTC、MATIC、ETHをネイティブに管理するオムニチェーンスマートコントラクトを使えば、以下のようなシステムが実現できます。

1.  BTC、MATIC、ETHのアセットをZetaChain上のプールにネイティブに、単純な送金（または同等の）トランザクションを通じて、ワンステップで入金することができます。
    
2.  ZetaChain上の単一のトランザクションで、それぞれのネイティブチェーン上のあなたのアドレスに引き出すことができます。
    
3.  もし誰かがこのプールを通してスワップしたいのであれば、ネイティブアセットを送ることで取引でき、その人はネイティブアセットを直接（例：BitcoinアドレスにBTCを直接）宛先に受け取ることができ、これらのトランザクションはすべて1ステップで行います。
    

オムニチェーン・マルチアセットプールでは、以下のことが可能です。

*   LPとスワップするユーザーの双方にとって、より少ないステップ（ガス、時間の節約になります）
    
*   スワップ＋引き出しが単一のトランザクションで行われ、メッセージングやブリッジングによる非同期タイミングに依存しないことによる、スリッページ最小化
    
*   ユーザーアセットはブリッジやラップされたアセットvaultに対する脅威にさらされないず、リスクプロファイルの大幅な減少
    

### 3.3.2 レンディングの例

オムニチェーンスマートコントラクトの機能は、クロスチェーンレンディングのような複雑なアプリケーションではさらに有利になる可能性があります。基本的な借入フローを想像すると、異なるチェーンとの間のメッセージで次のような手順になります（もちろん、これを実装する方法はたくさんあります）。

1.  チェーン1上にアセットAの担保を預ける。
    
2.  チェーン1にアセットAの担保を預ける。チェーン2にチェーン1の担保Aに対してBの借入を要求する。
    
3.  プロトコルはチェーン1の担保額を確認するメッセージを送信する。
    
4.  プロトコルはチェーン2に対して、元のリクエストを検証するメッセージを返送する。
    
5.  プロトコルは、チェーン1から受け取ったメッセージに基づくA/Bの（何らかのオラクル）価格に基づいて、チェーン2のBを一定量だけ借りることができる。
    
6.  プロトコルは借り手に金額を送信する。
    

その代わり、ZetaChain上のオムニチェーン対応貸出スマートコントラクトを使えば、貸出は次のようなステップになります。

1.  チェーン1のアセットAとチェーン2のアセットBを管理するzEVM上のAaveのようなコントラクトプールに担保を預け入れる。
    
2.  借り手は、その担保Aに対して、オラクルチェックに基づいてアセットBの借入を要求し、すべて単一の同期関数内で、ターゲットの宛先に送信される。
    

4\. ZRC-20\[4\]
===============

ZRC-20は、ZetaChainのオムニチェーンスマートコントラクトプラットフォームに統合されたトークン規格です。ZRC-20を使用すると、開発者は、接続された任意のチェーン上でネイティブアセットをオーケストレーションするdAppsを構築することができます。これにより、オムニチェーンDeFiプロトコルやオムニチェーンDEX、オムニチェーンレンディング、オムニチェーンポートフォリオ・マネジメントなどのdAppsが構築できます。さらに、複数のチェーン上のファンジブルトークンを含むあらゆるものを1つの場所から、極めて簡単に、まるですべてが1つのチェーン上にあるかのように構築できるようになります。

4.1 はじめに
--------

ZRC-20トークンは、Ethereumエコシステムで見られる標準的なERC-20トークンの拡張版で、ZetaChainに接続されたすべてのチェーン上のアセットを管理する能力が追加されています。Bitcoin、Dogecoin、他のチェーン上のERC-20同等物、他のチェーン上のガスアセットなど、あらゆるファンジブルトークンはZetaChain上でZRC-20として表され、（ERC-20など）他のファンジブルトークンと同じようにオーケストレーションできるかもしれません。

ZRC-20\[4\]

4.2 インターフェース
------------

ZRC-20はERC-20をベースに、ZetaChainのCross-Chain Transactions（CCTXs）と統合するために3つの追加関数といくつかの関連イベントを追加しています。

    pragma solidity 0.8.7;
    interface IZRC20 {
        function totalSupply() external view returns (uint256);
        function balanceOf(address account) external view returns (uint256);
        function transfer(address recipient, uint256 amount) external returns (bool);
        function allowance(address owner, address spender) external view returns (uint256);
        function approve(address spender, uint256 amount) external returns (bool);
        function transferFrom(
            address sender,
            address recipient,
            uint256 amount
        ) external returns (bool);
        function deposit(address to, uint256 amount) external returns (bool);
        function withdraw(bytes memory to, uint256 amount) external returns (bool);
        function withdrawGasFee() external view returns (address, uint256);
        event Transfer(address indexed from, address indexed to, uint256 value);
        event Approval(address indexed owner, address indexed spender, uint256 value);
        event Deposit(bytes from, address indexed to, uint256 value);
        event Withdrawal(address indexed from, bytes to, uint256 value);
    }
    

ZRC-20とERC-20を比較すると、入出金のための外部関数が追加され、それぞれに対応したイベントが追加されています。これにより、ZRC-20はERC-20用に構築されたあらゆるアプリケーションと完全に互換性があり、かつ極めてシンプルなインターフェースでオムニチェーン的な機能も実現できます。

### 4.2.1 `deposit`

ユーザーが接続されたチェーン上のZetaChain TSSアドレスにアセットを送信/預金すると、`deposit`は`zetacore`によって呼び出され、預金したアドレスで利用できるようになります。TX`message`にデータがある場合、システムコントラクト`DepositAndCall`が呼び出され、ターゲットzEVMコントラクト上の`onCrossChainCall`への呼び出しによってそのデータを転送します。`deposit`と `DepositAndCall`関数は CCTX モジュール（`zetacore` モジュール）アドレスによってのみコール可能です。

これはシステムコントラクトがどのように見えるかのスニペットで、ZetaChainネットワークによって管理されるTSSアドレスへの預金を受け取った後、`zetacore`によって`DepositAndCall`が呼び出される可能性があります。

    contract SystemContract {
        address public constant FUNGIBLE_MODULE_ADDRESS;
        // ...
        constructor(address fungibleModule) {
            FUNGIBLE_MODULE_ADDRESS = fungibleModule;
        }
        // ...
        function DepositAndCall(address zrc20, uint256 amount, address target, bytes calldata message) external {
            require(msg.sender == FUNGIBLE_MODULE_ADDRESS);
            require(target != FUNGIBLE_MODULE_ADDRESS && target != address(this));
            IZRC20(zrc20).deposit(target, amount);
            zContract(target).onCrossChainCall(zrc20, amount, message);
        }
    }
    

    // a contract that implements this interface may be called by a ZRC-20 deposit call
    interface zContract {
        function onCrossChainCall(
            address zrc20,
            uint256 amount,
            bytes calldata message
        ) external;
    }
    

### 4.2.2 スマートコントラクトチェーンからzEVMコントラクトを入金して呼び出す方法

これは、入金するためにAthens 2のTSSアドレスにトランザクションを`deposit`するために、Ethereumのチェーンから呼び出す例です。

    import { parseEther } from "@ethersproject/units";
    import { ethers } from "hardhat";
    // This is a constant address, the TSS address of the ZetaChain network.
    import { TSS_ATHENS2 } from "../systemConstants";
    // Primary function definition
    const main = async () => {
      // Get signer in order to write transction.
      const [signer] = await ethers.getSigners();
      // Sign a transaction that sends Ether to the TSS address.
      const tx = await signer.sendTransaction({
        to: TSS_ATHENS2,
        value: parseEther("100")
      });
      // That's it! ZetaChain will pick up the transaction.
      console.log("Token sent. tx:", tx.hash);
    };
    main().catch(error => {
      console.error(error);
      process.exit(1);
    });
    

代わりに`DepositAndCall`を行いたい場合、同様のパターンを行うことができますが、Depositコールにデータを含めることができます。この例では、zEVM上に存在する`swap`コントラクトを呼び出しています。

    import { BigNumber } from "@ethersproject/bignumber";
    import { parseEther } from "@ethersproject/units";
    import { getAddress, isNetworkName } from "@zetachain/addresses";
    import { ethers } from "hardhat";
    import { ZRC20Addresses, TSS_ATHENS2 } from "../systemConstants";
    import { network } from "hardhat";
    // Helper function to format data for sending a swap transaction
    const getSwapData = (zetaSwap: string, destination: string, destinationToken: string, minOutput: BigNumber) => {
      const params = getSwapParams(destination, destinationToken, minOutput);
      return zetaSwap + params.slice(2);
    };
    // Primary function definition
    const main = async () => {
      if (!isNetworkName(network.name) || !network.name) throw new Error("Invalid network name");
      // Here you're choosing the target token you want the swap to output based on the network
      const destinationToken = network.name == 'goerli' ? ZRC20Addresses['tMATIC'] : ZRC20Addresses['gETH']
      console.log("Swapping native token...");
      // Get a signer to write your transaction
      const [signer] = await ethers.getSigners();
      // Get the correct address of the swap contract (using a helper function)
      const zetaSwap = getAddress({
        address: "zetaSwap",
        networkName: "athens",
        zetaNetwork: "athens"
      });
      // Use formatting function to get the correct data format
      const data = getSwapData(zetaSwap, signer.address, destinationToken, BigNumber.from("0"));
      // Sign your transaction with Swap data.
      const tx = await signer.sendTransaction({
        data,
        to: TSS_ATHENS2,
        value: parseEther("0.5")
      });
      console.log("tx:", tx.hash);
    };
    main().catch(error => {
      console.error(error);
      process.exit(1);
    });
    

初期にサポートされるアセットは、Bitcoinを含むすべての接続されたチェーン上のZETAとガスアセットです。プロトコルは、将来のアップグレードですべてのファンジブルトークンに拡張される予定です。

### 4.2.3 BitcoinからzEVMコントラクトを入金・呼び出しする方法

Bitcoinでテストするためには、`OP_RETURN`を設定できるウォレットを使用する必要があります。

ZRC-20やZetaChainエコシステムの残りの部分で使用するためにZetaChainにBitcoinを入金するには、ZetaChainのTSSによって管理されるアドレスにBitcoinを送る必要があります。トランザクションは、以下のドキュメントにあるようにフォーマットされた`OP_RETURN`を含むべきです（｜記号は可読性向上のためのもので、実際のメッセージにはそれらを含めるべきではありません）。

    z|0xcc7bb2d219a0fc08033e130629c2b854b7ba9195|00000000000000000000000000000000000000000000000000000000000
    

*   文字「z」は定数で、`OP_RETURN`が有効であることを確認するためにZetaCoreによって使用されます。
    
*   アドレスは、トランザクションがzEVMコードを実行する場合はコントラクト、zBTCを送りたいだけの場合はアカウントにすることができます。
    
*   メッセージは任意であり、宛先のコントラクトによって解析されます（ある場合のみ）。
    

無効な情報が送信された場合（例：無効なアドレス）、アセットは元の送信者アドレスに戻されます。

要約すると、zEVMのBTCトランザクションは次のようになります。

*   ユーザーはBitcoinネットワーク上で1BTCをBitcoinTSSアドレスに送り、txに（`OP_RETURN`経由で）「deposit to 0x1337」というメモを（口語で）追加します。
    
*   このTXを受信すると、ZetaCoreステートマシンは、手数料を差し引いた1zBTCを0x1337に鋳造(mint)してクレジットするために、deposit (0x1337, 1e8)を呼び出します。
    
*   0x1337がExternally Owned Account（EOA）であれば、それでおしまいです。それがコントラクトであれば、ZetaCoreは`OP_RETURN`メモで指定されたメッセージを送信する`onCrossChainMessage`関数を呼び出します。
    

TSSアドレスはBTCを保持しており、このBTC ZRC-20コントラクトの内部で所有権が追跡されます。

### 4.2.4 `withdraw`

`withdraw`関数は、任意のExternally Owned Account (EOA)またはスマートコントラクトから呼び出されます。この関数は、金額が焼却され、Withdrawal()イベントを残すことを除けば、transfer()と同じようなものです。このイベントは`zetacore`モジュールでCCTXをトリガーし、`zetaclient`はそれをピックアップしてアウトバウンドのtxを処理します。この例では、ある与えられた2つのトークンのプールを持つ、既存のUniswapデプロイメントを使用しています。`onCrossChainCall`が呼び出されると、ターゲットZRC-20トークンへのスワップを実行し、それをネイティブチェーン上のアドレスに引き出します。

    contract ZEVMSwapApp is zContract {
        address public router02; 
        constructor(address router02_) {
            router02 = router02_;
        }
        
        // Call this function to perform a cross-chain swap
        function onCrossChainCall(address zrc20, uint256 amount, bytes calldata message) external override {
            address targetZRC20;
            address receipient;
            uint256 minAmountOut; 
            (targetZRC20, receipient,minAmountOut) = abi.decode(message, (address,address,uint256));
            address[] memory path;
            path = new addressUnsupported embed;
            path[0] = zrc20;
            path[1] = targetZRC20;
            // Approve the usage of this token by router02
            IZRC20(zrc20).approve(address(router02), amount);
            // Swap for your target token
            uint256[] memory amounts = IUniswapV2Router01(router02).swapExactTokensForTokens(amount, minAmountOut, path, address(this), block.timestamp);
            // Withdraw amountto target recipient
            IZRC20(targetZRC20).withdraw(abi.encodePacked(receipient), amounts[1]);
        }
    }
    

この例がいかにシンプルであるかに注目してください。20行程度のコード（その多くは汎用コード）で、ユーザーがネイティブアセットと他のネイティブアセットを交換できるクロスチェーンスワップdAppを作成できます。これらのシンプルな機能を組み合わせることで、オムニチェーンアプリケーション構築のための強力かつシンプルなソリューションが生まれます。

5\. オムニチェーンスマートコントラクトを利用した流動性プール\[5\]
=====================================

流動性プールは、ZetaChainの重要な機能と、Cryptoエコシステム全体のためのユーザー体験の向上（手数料の低下、より流動的な取引所、より多用途な金融アプリケーション）の両方を促進します。ZetaChain環境のプールは、コアZETAプール、追加zEVMプール、外部ZETAプールという3種類の主要バケットに分類されます。

5.1 コアZETAプール
-------------

\[ZETA\] / \[Gas ZRC-20\] Uniswap Pool (on zEVM)は、そのチェーンにアウトバウンドトランザクションを書き込むためにZetaChainによって必要とされるコアプールです。チェーンのサポートが追加されるたびに、ZETAとそのチェーンのネイティブガスアセットの間の対応するプールも作成されます。

ここでは、UniswapV2コントラクトがZETA/gas プールをどのように制御するかを視覚化することができます。流動性は、接続されたチェーンのTSSアドレスに提供され、その後、Uniswap（または任意の交換コントラクト）は、ZETAまたは他のアセットに対してそれらのアセット（ZRC-20）を使用することができます。

コアZETAプール\[5\]

例えば、ネイティブガス（ZRC-20）とZETAをペアにしてアウトバウンドトランザクションの支払いを行うコアプールを使って、トランザクションがどのように機能するかを見ることができます。

ZRC-20を使ったzEVM上のDEX\[5\]

5.2 追加zEVMプール
-------------

どのような流動性プールもzEVM上に作成することができます。ZetaChain上に通常のERC-20トークンを展開し、ZRC-20を通じて外部チェーン・トークンを組み込み、シングルチェーンEVM上と同様に、アプリケーションに必要な流動性プールのあらゆる組み合わせを作成することができます。例えば、ユーザーが異なるアセットに対してより流動的に取引できるように、有用な\[ZETA\]/\[Stablecoin\]や\[Gas\]/\[Stablecoin\]プールを作成することができます。

5.3 外部ZETAプール
-------------

ZETAは、スマートコントラクトのガス代やクロスチェーンメッセージングに使用されるように、ZetaChain上だけでなく、あらゆる接続先チェーン上の両方に存在するオムニチェーントークンです。各チェーン上の\[ZETA\] / \[Gas\]などの特定のプールは、メッセージングによるクロスチェーンの価値移転を促進するアプリケーションにとって有用です。また、開発者はメッセージングに使用するために、ZETAを取得するための外部チェーン上のプールを必要とします。

6\. クロスチェーンメッセージング\[6\]\[7\]
============================

クロスチェーンメッセージングは、ZetaChainを含む、任意の接続されたチェーンから任意の接続されたチェーンにメッセージを送ることを可能にします。これらは、一般的にすべてのチェーン間で維持する最小限のロジックまたは状態を必要とし、異なるチェーン間で渡される必要があるデータが一方向にのみ転送されるアプリケーションのために最も理にかなっています。新しいラップアセットを必要とせず、メッセージングを通じてあらゆるデータや価値を送ることができます。

6.1 コネクター
---------

ZetaChainコネクターは、接続された任意のチェーン間でクロスチェーンメッセージ（データと値）を送信することができます。

### 6.1.1 はじめに

Zetaコネクターを使用してクロスチェーンのスマートコントラクトを作成するために、あなたのコントラクトは以下のようになります。

*   メッセージを送信するために`connector.send`を呼び出す
    
*   メッセージを受信するために`onZetaMessage`を処理する
    
*   メッセージを戻すために`onZetaRevert`を処理する
    

### 6.1.2 チェーン間でデータと値の送信

他のチェーンと相互作用するために、自分のコントラクトから`connector.send`を呼び出します。

    interface ZetaInterfaces {
          /**
          * @dev Use SendInput to interact with the Connector: connector.send(SendInput)
          */
          struct SendInput {
              /// @dev Chain id of the destination chain. More about chain ids https://docs.zetachain.com/learn/glossary#chain-id
              uint256 destinationChainId;
              /// @dev Address receiving the message on the destination chain (expressed in bytes since it can be non-EVM)
              bytes destinationAddress;
              /// @dev Gas limit for the destination chain's transaction
              uint256 destinationGasLimit;
              /// @dev An encoded, arbitrary message to be parsed by the destination contract
              bytes message;
              /// @dev ZETA to be sent cross-chain + ZetaChain gas fees + destination chain gas fees (expressed in ZETA)
              uint256 zetaValueAndGas;
              /// @dev Optional parameters for the ZetaChain protocol
              bytes zetaParams;
          }
        }
    
        interface ZetaConnector {
            function send(ZetaInterfaces.SendInput calldata input) external;
        }
    

### 6.1.3 **onZetaMessage**

ソースコントラクトが`connector.send`を呼び出した後、ZetaChainシステムは、メッセージを宛先チェーンに転送し、コントラクトアドレス`destinationAddress`で`onZetaMessage`を呼び出します。オプションとして、送信側コントラクトは、価値をクロスチェーンに移動させるためにいくつかのZETAトークン（`ZetaAmount`、ZetaConnectorコントラクトによって使われることをApprove）を提供し、宛先チェーン相互作用のためのガス料金をカバーすることが可能です。ZetaChainシステムは、ZETAトークンを宛先チェーンに移動し、それを受信スマートコントラクト`destinationAddress`に転送します。宛先チェーンは、このインターフェイスを実装するスマートコントラクトをdeployする必要があります。

    interface ZetaInterfaces {
          struct ZetaMessage {
              bytes zetaTxSenderAddress;
              uint256 sourceChainId;
              address destinationAddress;
              /// @dev Remaining ZETA from zetaValueAndGas after subtracting ZetaChain gas fees and destination gas fees
              uint256 zetaValue;
              bytes message;
          }
        }
    
        interface ZetaReceiver {
          function onZetaMessage(ZetaInterfaces.ZetaMessage calldata zetaMessage) external;
        }
    

関数内部では、現在のスマートコントラクトが、送信側コントラクトが送信した`ZetaAmount` ZETAトークン（ガス代を差し引いたもの）をすでに受け取っていると仮定することができます。

### 6.1.4 **onZetaRevert**

このコントラクト関数呼び出しが何らかの理由で失敗した場合、ZetaChainシステムは、送信側スマートコントラクトの`onZetaRevert`関数を呼び出します。焼却済ZETAトークンは送信側のコントラクトに払い戻され、送信側のコントラクトはこのクロスチェーンメッセージに関する当該アクションを適切に戻す必要があります。

送信元チェーンのスマートコントラクトもこのインターフェイスを実装する必要があります。

    interface ZetaInterfaces {
          struct ZetaRevert {
              address zetaTxSenderAddress;
              uint256 sourceChainId;
              bytes destinationAddress;
              uint256 destinationChainId;
              /// @dev Equals to: zetaValueAndGas - ZetaChain gas fees - destination chain gas fees - source chain revert tx gas fees
              uint256 remainingZetaValue;
              bytes message;
          }
        }
    
        interface ZetaReceiver {
          function onZetaRevert(ZetaInterfaces.ZetaRevert calldata zetaRevert) external;
        }
    

送信先トランザクションが失敗した場合、この関数でアプリケーションレベルのロールバックが発生するはずです。

### 6.1.5 まとめ

ZetaChainのコネクターを使用してあなたのdAppsをマルチチェーンに適応するために、あなたはZetaChainによってサポートされる複数のチェーンにコントラクトをデプロイする必要があります。それらコントラクトは、`onZetaMessage`および`onZetaRevert`コールバックを実装し、`connector.send`を呼び出すことによって、互いの間でメッセージと値を送信することができるようになります。

6.2 用例
------

[https://www.zetachain.com/docs/developers/cross-chain-messaging/connector-api](https://www.zetachain.com/docs/developers/cross-chain-messaging/connector-api)

上記のページの下部に、用例一覧が載っています。クロスチェーンメッセージングによって、以下のことに使うことができます。

*   クロスチェーンメッセージ
    
*   マルチチェーン価値転送
    
*   クロスチェーンカウンター
    
*   クロスチェーンNFT
    
*   マルチチェーンスワップ
    

7\. ガス代
=======

7.1 オムニチェーンスマートコントラクトのガス代\[8\]
------------------------------

ZetaChain上のスマートコントラクトと対話するとき、ユーザーはそのトランザクションのためにガスに費やされる価値の一部を含んでいます。

スマートコントラクトのデプロイメントとスマートコントラクトの呼び出しは、実行するためにガスを必要とします。ユーザはZRC-20入金、メッセージにコントラクト呼び出しを含む、またはZetaChainに直接接続し、zEVMにすでに展開されているコントラクトと対話することにより、外部チェーンからzEVMコントラクトを呼び出すことができます。

ZetaEVMスマートコントラクトのガス市場/メカニズムは、Ethermintに基づいており、EIP 1559 Ethereumガス代と同様の動作をします。このガスシステムは、悪意のあるユーザーがネットワークをスパミングすることを抑止するために構築されています。

7.2 クロスチェーンメッセージングのガス代\[9\]
---------------------------

ユーザー（ウォレット、コントラクト）は、ZetaChainを通してチェーン間でデータと価値を送るために手数料を支払う必要があります。ユーザーは、接続されたチェーン上でZETA（およびメッセージデータ）をコネクターコントラクトに送信することにより、手数料を支払います。このZETAは、バリデータ／ステーカー／エコシステムプールへの支払い、および送信先でのガスへの支払いに使用されます。ユーザーにとっては、これがすべて1つのトランザクションにバンドルされます。

### 7.2.1 データサイズ/ストレージに応じた料金の変動

ネットワーク料金には、ユーザーがチェーン上で送信しようとするメッセージサイズ（バイト）に基づくコンポーネントがあります。

これは、ユーザーが経済的に健全でありながら送信できるデータ量を調整するものです。非常に複雑なデータを送信する場合は、より多くのコストがかかります。この仕組みは、スマートコントラクトの手数料の仕組みと同様に、今後の開発により、変動相場制へと移行する予定です。

7.3 Base Fee\[8\]\[9\]
----------------------

ZetaChainは、あらゆるトランザクション、クロスチェーンメッセージングトランザクション、またはスマートコントラクトに対して、（例えば）0.01 ZETAのBase Flat Feeを含んでいます。このBase Feeは、ネットワークトラフィックと混雑状況に基づいてネットワークによって調整可能であり、焼却されます。

8\. 参考・引用文献
===========

\[1\] ZetaChain Architecture Overview, [https://www.zetachain.com/docs/developers/concepts/zetachain-architecture-overview](https://www.zetachain.com/docs/developers/concepts/zetachain-architecture-overview)（アクセス日：2022年11月28日）

\[2\] FAQ, [https://www.zetachain.com/docs/learn/faq](https://www.zetachain.com/docs/learn/faq)（アクセス日：2022年11月28日）

\[3\] Omnichain Smart Contracts vs. Messaging, [https://www.zetachain.com/docs/developers/concepts/smart-contracts-vs-messaging](https://www.zetachain.com/docs/developers/concepts/smart-contracts-vs-messaging)（アクセス日：2022年11月28日）

\[4\] ZRC-20, [https://www.zetachain.com/docs/developers/omnichain-smart-contracts/zrc-20](https://www.zetachain.com/docs/developers/omnichain-smart-contracts/zrc-20)（アクセス日：2022年11月28日）

\[5\] Liquidity Pools, [https://www.zetachain.com/docs/developers/omnichain-smart-contracts/liquidity-pools](https://www.zetachain.com/docs/developers/omnichain-smart-contracts/liquidity-pools)（アクセス日：2022年11月28日）

\[6\] Cross-Chain Messaging, [https://www.zetachain.com/docs/developers/cross-chain-messaging/overview](https://www.zetachain.com/docs/developers/cross-chain-messaging/overview)（アクセス日：2022年11月28日）

\[7\] Connector, [https://www.zetachain.com/docs/developers/cross-chain-messaging/connector-api](https://www.zetachain.com/docs/developers/cross-chain-messaging/connector-api)（アクセス日：2022年11月28日）

\[8\] Gas Fees, [https://www.zetachain.com/docs/developers/omnichain-smart-contracts/gas-fees](https://www.zetachain.com/docs/developers/omnichain-smart-contracts/gas-fees)（アクセス日：2022年11月28日）

\[9\] Gas Fees, [https://www.zetachain.com/docs/developers/cross-chain-messaging/gas-fees](https://www.zetachain.com/docs/developers/cross-chain-messaging/gas-fees)（アクセス日：2022年11月28日）

---

*Originally published on [hashigo](https://paragraph.com/@hashigo/zetachain-2)*
