2020.10.07

ガスレス(Gas-Less)でUX向上させるーEthereum Gas Station Network(GSN)

Pocket

はじめに

こんにちは。次世代システム研究室のL.W.です。

最近は、DeFiが流行っていて、トランザクションはイーサリアムネットワークに殺到して、ネットワークがかなり混んでいる状態となっています。

スループットの高めるソリューションであるLayer2スケーラビリティに再び注目を浴びています。

実際にはスケーラビリティ以外に、イーサリアムへのアクセルを妨げる最大の要因の1つはユーザー体験(UX)の悪さと言われています。

イーサリアムの分散型アプリケーション(DAPP)にアクセスしようとしている日常のユーザーにとって、ガス代(取引手数料、ETHで支払う)を払う必要がある敷居は非常に高くなっています。ただし、イーサリアムネットワークを適切に保護するには、ネットワーク内のガスが欠かせないです。



出典: https://medium.com/@RongxinZhang/meta-transactions-gasless-transactions-7c0ce64ef9bd

 

現在の主なDAPPにおいて、イーサリアムのスマートコントラクトとやりとりする流れは上の図のようです。
  1. 分散型アプリケーション(DAPP)のサービス提供者はユーザー向けのフロントエンドを提供する。
  2. ユーザーは自分の管理していいるアカウントのプライベートキーでトランザクションを署名し、DAPPサービスを通して、スマートコントラクトを呼び出す。所持するETHをGAS代に支払います。
  3. ユーザーはイベントをリッスンする。
 

DeFiで人気のUniswapはまさにこのような設計となります。

しかし、これでは、DAPPと対話するために、ユーザーはガスの代金を支払うためにETHを保持する必要があります。ほとんどの経験豊富なイーサリアムユーザーにとって問題ではありません。 ただし、新規ユーザーにとって、これは参入障壁として深刻です。ユーザーは法定通貨でイーサを購買したり、取引所で所持のERC20トークンでETHとスワップしたりすることの敷居も低くないでしょう。

ETHなしのせいで、エアドロップでもらった各種のERC20トークンは眠らせるしかないことはもったいないじゃないでしょうか。

一体、解決策がありますか。

 

Meta Transaction(メタトランザクション)

答えはメタトランザクションです。メタトランザクションはガスレストランザクション(Gas-Less Transaction、ガス要らない)を可能にします。

提案はERC-865です。

メタトランザクションにより、ユーザーはトランザクション料金(ガス代)を支払うことなくブロックチェーンと対話できます。これにより、ユーザーはブロックチェーンのメカニズムや取引手数料の市場理論を理解する必要がなくなるため、よりシームレスなUXにつながります。



出典: https://medium.com/biconomy/how-to-integrate-native-meta-transactions-in-your-defi-dapp-3054272f14f1

 

上の図のように、基本的に、メタトランザクションは通常のネットワークトランザクションとほぼ同じですが、リレーの役割を果たすリレイヤー(Relayer)と呼ばれる人物が追加されています。メタトランザクションでは、ユーザーは引き続き送金しようとするトランザクションをメッセージとして署名して、リレイヤーに送信します。リレイヤーはユーザーの代わりに、ガスを支払い、この署名済みのトランザクションの受信アドレスに送信します。

端的に言うと、秘密鍵をリレイヤーに預けず、ガスの支払いだけをリレイヤーに肩代わりさせることです。

DAPPサービスの提供者はメタトランザクションを活用することで、分散型アプリケーションのユーザー体験(UX)を大幅に向上できることが期待されています。

リレー方式により、二つ種類のメタトランザクションに分けられます。Centralized RelaysとDecentralized Relaysです。

 

Centralized Relays(中央型リレー)


出典: https://medium.com/@RongxinZhang/meta-transactions-gasless-transactions-7c0ce64ef9bd

 

中央型リレーの流れは上の図のようです。
  1. 分散型アプリケーション(DAPP)のサービス提供者はユーザー向けのフロントエンドを提供する。
  2. ユーザーは自分の管理しているプライベートキーでメッセージを署名する。これはオフチェーンなので、ガスがかからない。署名済みのメッセージと署名情報をDAPPサーバーに送る。
  3. DAPPサーバー側で受信したメッセージの署名情報とNonce値をチェックし、問題なければ、トランザクションに詰める。サーバー側の管理しているアカウントのプライベートキーで署名し、ターゲットのコントラクトを呼び出す。
  4. ユーザーは自分のメッセージの通りにトランザクションが実行したかどうかイベントをリッスンする。場合によってはユーザーは法定通貨あるいは所持するERC20トークンでDAPPサービス提供者にETHのガス代金を支払う。
 

これはDAPPのサービス提供者がメタトランザクションを統合するための最も簡単な方法ですが、分散型の精神に反します。

分散型ファイナンス(DeFi)とトラストレスランザクションのコンセプトを考えると、中央型リレーはネットワークの単一障害点として機能するため、分散型思想のブロックチェーンと矛盾します。
言い換えると、DAPPのサービス提供者はトランザクションを検閲することが容易にできます。または、リレーサービスがダウンすると、アプリケーションも一緒にダウンする可能性もあります。

最近のニュースでは、USDCがメタトランザクションが使用可能と言う報道は話題となりましたね。

Ethereum上のドル建てステーブルコインであるUSDCのコントラクトがアップデートされました。今回のアップデートで本来ETHで支払うべき送金手数料を第三者に肩代わりしてもらうことができ、「メタトランザクション」と呼ばれる機能が追加されたと言うことです。

USDCのメタトランザクションを利用するためには、中央型のリレーのサービスの提供が欠かせないですが、いまだに構築されていないかと思っています。このサイトからすると、メタトランザクションは3回しか呼び出せないです。

中央型リレーをイメージするためには、デモを作ってみましたが、体験してください。手順は以下の通りです。
  1. MetaMaskと言うブラウザウォレットを事前にインストールし、テストネットのKovanまたはRopstenにしておく。
  2. DAPP利用者としてのアカウント(ETHなし)でメッセージを入力し、署名する。
  3. リレイヤーとしてのアカウント(ETHあり)に切り替えて、メッセージと署名情報をトランザクションに詰めて、署名し、イーサリアムネットワークにブロードキャストする。
  4. 補足:テストコインはここでの「Mint GYEN for test」ボタンをクリックして取得できる。(もちろん、ガスがかかりません。)
 

Decentralized Relays(分散型リレー)


出典: https://medium.com/@RongxinZhang/meta-transactions-gasless-transactions-7c0ce64ef9bd

 

分散型リレーの流れは上の図のようです。
  1. 分散型アプリケーション(DAPP)のサービス提供者はユーザー向けのフロントエンドを提供する。
  2. ユーザーは自分の管理しているプライベートキーでメッセージを署名する。これはオフチェーンなので、ガスがかからない。署名済みのメッセージと署名情報をDAPPサーバーに送る。
  3. サーバー側の管理しているアカウントのプライベートキーで受信したメッセージを署名し、Relayコントラクトを呼び出す。DAPPサーバー側でメッセージのチェックではなく、インフラとしてのRelayコントラクトに任せることでDAPPサーバーは不特定多数のユーザーのメッセージの処理、送信が可能となる。複数のDAPPサービスの分散型リレーにより、検閲性を避ける構えである。
  4. Relayコントラクトからのイベントをリッスンする。メッセージはリレーされるかどうか確認できる。
  5. RelayコントラクトはInternal Transaction(コントラクト間の呼出)でターゲットのコントラクトを呼び出す。
  6. ユーザーは自分のメッセージの通りにトランザクションが実行したかどうかイベントをリッスンする。場合によってはユーザーは法定通貨あるいは所持するERC20トークンでDAPPサービスにETHのガス代金を支払う。
言うまでもなく、分散型ネットワークでは、リレー機能を分散型にするのが理想的なソリューションです。
分散型リレーは、トランザクションプール(署名済みのメッセージのキューのこと)を監視し、セカンダリマイナーとして機能できます。
ただし、それでも同期の問題が発生します。 メタトランザクションでは、リレイヤーは一度に1つのトランザクションしか処理できず(トランザクションの署名ではnonceの問題があるから)、各リレイヤーは最も収益性の高いトランザクションのみを選択します。 これにより、最も収益性の高い取引をめぐって競合することで、1人のマイナーだけが成功し、他のすべてのマイナーは失敗してお金を失うことになります。

ではどのようにこの課題が解決できますか。

Gas Station Network (GSN)はイーサリアムの採用を推進するさまざまなクリプトプロジェクトのコンソーシアムで構成され、コミュニティ主導のオープンソースに取り組んでいます。

Ethereum Foundationの2020/Q2の助成金も受けて、「With GSN, gasless clients can interact with Ethereum contracts without users needing ETH for transaction fees」と言うスローガンを掲げて、実現に向けて、開発が急いでいます。

GSN の方々の努力で、メタトランザクションを分散型的かつトラストレスに応用できるSDKが世に出せるのは近づいています。

では、UXの向上に期待できるGSNのことを一緒に覗いてみましょうか。

 

GSN(Gas Station Network)

全体像


出典: https://docs.opengsn.org/learn/index.html

 

コンポーネント説明

クライアント

DAPPを利用するウォレットのこと。

ガスのETHを必要とするEthereumトランザクションに署名する代わりに、クライアントは実行したいトランザクションに関する情報を含むメッセージ(メタメッセージ)に署名し、それをProvider通してRelayサーバーに送信します。

 

Provider

GSNに接続するプロバイダー。ProviderはHTTP通信でRelayサーバーとやりとりする。

GSNチームはこれをSDKとして世に出せます。

 

MetaTx Relay server

HTTPで受信したメタメッセージを処理するサーバー。

管理するアカウントでメタメッセージを署名し、メタトランザクションを作成し、イーサリアムネットワークにブロードキャストする。

ベストプラクティスとしては、すべてのDAPPサービス提供者が独自のリレーサーバーを構築し、独自のユーザーにサービスを提供することです。他のDAPPサービスからのユーザーにサービスを提供するためのリレー手数料も請求することできます。

DAPPのリレーサーバーが利用できない場合(DoS攻撃によるなど)、クライアントは、サービスを提供する他のDAPPのリレーサービスを受けます。

参加するRelayサーバーが多いほど、GSNの堅牢性が取れます。

複数のRelayサーバーで構成されるGSNには、どのようにメタメッセージを割り振りますか。

まずクライアント(利用側)でRelayサーバーを指定することができます。

クライアント側で指定しない場合には、一番反応速い(直ぐにサービス提供できる見込み)Relayサーバーを無作為に選出され、リレーを行わせます。

 

Paymaster Contract

最終的にガスを支払うコントラクトです。

リレイヤーがメタトランザクションのガスを支払ったが、Paymasterはリレイヤーにリファンドします。

アクセスコントロールとガスのリファンドのロジックは実装されています。

PaymasterはRelayHubにETHをデポジットして、このバランスでメタトランザクションを処理したリレーサービスにガスを支払います。

メタトランザクションを受け入れるか拒否するかを決定するためのビジネスロジックもpreRelayedCall方法で実装できます。
function preRelayedCall( GsnTypes.RelayRequest calldata relayRequest, bytes calldata signature, bytes calldata approvalData, uint256 maxPossibleGas ) external override virtual returns (bytes memory context, bool) { 
    _verifyForwarder(relayRequest); 
    // メタトランザクションのFromアカウントを判別する 
    // require(relayRequest.request.From == my_User, "not support"); 
    // メタトランザクションのターゲットコントラクトを判別する 
    // require(relayRequest.request.to == my_Contract, "not support");           
    // メタトランザクションを受け入れる。 
    // return (context, false); 
    // メタトランザクションを拒否する。
    // return (context, true); 
}
以下の方式が挙げられます。
  1. ホワイトリスト。Paymasterコントラクトでホワイトリストを維持し、メタトランザクションのFromアドレスあるいはToアドレスはホワイトリストにある場合のみ受け入れます。
  2. トークンでガス代返還。メタトランザクションのFromアドレスにはあるトークンの残高があり、かつUniswapなどのDEXのAPIを通してETHとスワップでき、スワップできたETHが支払ったガス代をカバーできるならば、受け入れます。
  3. ターゲットコントラクトを指定する。あるスマートコントラクトに関わる専用のサービスを提供する場合、メタトランザクションのToアドレスのスマートコントラクトをPaymasterで指定し、受け入れます。
  4. などなど
 

RelayHub Contract

ハブのような機能を提供するスマートコントラクトです。将来的にGSNチームはこれを共通インフラとしてメインネットワークにデプロイします。

RelayHubは、クライアント、リレーサーバー、Paymasterを接続するため、参加者同士はお互いをトラストする必要がありません。

RelayHubの主な役割は以下のようです。
  1. 利用できるリレーサービスのURLのリストを維持する。DAPPのリレーサーバーがダウンしたときにクライアントが最適なリレーサーバーを見つけることに役に立ちます。サードパーティのリレーサーバーでトランザクションの検閲も防げます。
  2. リバランス(ガスタンク)。独自のリレーサービスを提供するPaymasterのETHのバランスを取り直すことができます。そして、Paymasterがリレーサービスを確実に返済するように保証します。
  3. ステーキング。リレーサービスを提供するリレイヤーには、RelayHubでETHをステーキングする必要があります。不正を行ったリレイヤーをペナルティし、デポジットを全額を没収します。
 

TrustedForwarder Contract

メタトランザクションのFromアドレス(送信者)の署名とNonce(replay防止)を検証するコントラクトです。将来的にGSNチームはこれも共通インフラとしてメインネットワークにデプロイします。

メタトランザクションのターゲットコントラクトはセキュリティのためにこのコントラクトを信頼する必要があります。TrustedForwarderでパスされたメタトランザクションのみはReceipt Contractで実行されます。

Receipt Contract

メタトランザクションのターゲットコントラクトです。例えば、ステーブルコインサービスを提供する場合、Receipt Contractはステーブルコインのコントラクトとなります。

GSNのメタトランザクションをサポートするために、ReceiptコントラクトはBaseRelayRecipientコントラクトから継承し、TrustedForwarderコントラクトのアドレスを指定し、msg.senderを_msgSender方法に置き換える必要があります。
// Receipt ContractはBaseRelayRecipientを継承する
contract MetaCoin is BaseRelayRecipient {

    string public symbol = "META";
    string public description = "GSN Sample MetaCoin";
    uint public decimals = 0;
    mapping(address => uint) balances;
    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    constructor(address forwarder) public {
        // TrustedForwarderコントラクトを信頼した上で、指定する
        trustedForwarder = forwarder;
    }

    function transfer(address receiver, uint amount) public returns (bool sufficient) {
        // msg.senderを_msgSender()で置き換える
        if (balances[_msgSender()] < amount) return false;
        balances[_msgSender()] -= amount;
        balances[receiver] += amount;
        emit Transfer(_msgSender(), receiver, amount);
        return true;
    }
}
TrustedForwarderコントラクトからReceipt Contractを呼び出す場合のみ、_msgSender()方法はメタトランザクションのFromアドレスを返却します。他の場合には、msg.senderを返却することとなります。

 

GSNの全体の流れ

  1. ガスレスのクライアントはGSNProvider通して、一番速く利用できるリレーのサービスを探す。
  2. メタメッセージをHTTPリクエスト通して、1で探されたリレーサーバーに送信する。
  3. リレーサーバー側でRelayHub Contractと言うスマートコントラクトのステートを読み、Paymaster contractがガスの支払いに十分なETHを持っており、メタトランザクションを受け入れることを確認する。
  4. リレーサービスで署名済みのトランザクションをHTTPレスポンスでクライアントに返信する。
  5. リレーサービスは管理するアカウントでガスを支払って、RelayHub Contractを呼び出す。
  6. RelayHub Contractはinternal transaction(コントラクト間の呼出)でTrustedForwarder contractを呼出す。
  7. TrustedForwarder contract側で最初のメタメッセージの署名とnonceをチェックし、問題がなければ、ターゲットのコントラクトを呼び出す。
 

デモ

弊社の日本円と連動(円ペッグ)したステーブルコイン「GYEN」(GMO Japanese YEN)はGSNに参入するデモを作ってみました。

ガスレスのGYENの送金を体験することができます。(MetaMaskと言うブラウザウォレットを事前にインストールし、ネットワークをKovanまたはRopstenにしておく)

 

GSNの参照資料

GSNv2 GitHub

GSNv2 のマニュアル

GSNv2 の公式サイトでのデモ

GSNのNetworks

 

まとめ

近くGYENもサービス提供開始となりますが、GYENのようなトークンだけが持てば、イーサリアムでのDeFiを楽しめるような未来を楽しみにしましょう。

ガスがなくても容易にイーサリアムを触れることが現実味を帯びて始めますが、GSN利用でかかったガスは直接にターゲットコントラクトを呼び出すことによりかかったガスの数倍に至る課題があります。

ガスレスのUX向上の代償は誰かにより多くのガス代金を肩代わりしてもらうことですね。

イーサリアム2.0の本番稼働の足音が近づいてきて、ガス手数料をどのぐらい軽減できるか、これから見守っていきます。

 

さいごに

次世代システム研究室では、グループ全体のインテグレーションを支援してくれるアーキテクトを募集しています。アプリケーション開発者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ募集職種一覧からご応募をお願いします。

皆さんのご応募をお待ちしています。

Pocket

関連記事