🏦

プロトコルネイティブなエスクロー

2023/03/23に公開

XRP Ledger とは

XRP LedgerはBitcoinやEthereumなどと同じ分散型のパブリックブロックチェーンです。PoWやPoSとは異なる独自のコンセンサスアルゴリズムが用いられています。
トークン機能やDEX機能をプロトコルネイティブに搭載しており、強力な決済機能があります。決済機能だけでなくNFTやAMM(開発中)、Hooks(スマコン/開発中)など様々な機能を搭載しています。

エスクロー

エスクローは、第三者機関を介して取引が行われる際に、取引の安全性を確保するために利用されます。取引に関わる各当事者が、資産をエスクローに預けることで、取引に関する契約条件が満たされるまで保護されます。エスクローに預けられた資産は、取引が完了すると各当事者に送金されます。

エスクローの利点

エスクロー機能を利用することで、取引に関わる各当事者が、取引の条件が満たされるまで安心して取引を進めることができます。特に、高額な取引を行う場合や、信頼関係が薄い相手と取引をする場合には、エスクロー機能を利用することがおすすめです。エスクロー機能は、通貨を預けることで取引の条件を確認するため、取引に関する紛争を回避することもできます。

XRP Ledgerでのエスクロー

XRP Ledgerには、このエスクロー機能がスマートトランザクタ(コントラクトの記述が必要ないネイティブな機能)として実装されており、XRP Ledger自体が第三者機関そのものとなります。

https://xrpl.org/ja/escrow.html

利用可能なエスクロー

XRP Ledgerでは次のようなエスクローが利用可能です。

時間に基づくエスクロー

エスクローをリリースするまでに一定時間の経過が必要となります。
例えば一定量のXRPを1年間プロトコルでロックし、1年後に利用可能にするようなことができます。

https://xrpl.org/ja/send-a-time-held-escrow.html

条件に基づくエスクロー

エスクローをリリースするにはエスクロー作成者がエスクロー作成時に作成した"フルフィルメント"が必要です。
例えば、物品の売買を行う際に、購入者が物品を受け取った時点で"フルフィルメント"を公開することで取引を成立させることが可能です。

https://xrpl.org/ja/send-a-conditionally-held-escrow.html

エスクローの例

エスクローは、取引に関する信頼性を高めることができるため、多くの場面で利用されています。以下に、エスクローが利用される代表的な例を紹介します。

オンラインマーケットプレイス

オンラインマーケットプレイスでは、買い手と売り手の間で取引が行われます。取引に関する紛争が発生した場合、第三者機関によるエスクロー機能を利用することで、紛争を解決することができます。例えば、買い手が商品を受け取ったことを確認した後に、支払いが行われるようにすることで、売り手が商品を送ったにもかかわらず、支払いがされないという問題を回避することができます。

不動産取引

不動産取引においても、エスクロー機能が利用されることがあります。例えば、買い手が支払いを行った後に、売り手が物件の所有権を移転するようにすることで、取引に関する紛争を回避することができます。

クラウドファンディング

クラウドファンディングでも、エスクロー機能が利用されることがあります。例えば、支援者が寄付を行った後に、目標金額が達成された場合にのみ、寄付が実際に行われるようにすることで、目標金額が達成されなかった場合に支援者が損失を被ることを回避することができます。

エスクローに関連するトランザクションについて

エスクローに関連するトランザクションには、以下の3種類があります。

EscrowCreate

エスクローを作成するためのトランザクションです。このトランザクションで指定するパラメータには、エスクローの作成者、宛先、預けるXRPの量、期限や条件などが含まれます。このトランザクションを実行することで、エスクローが作成され、預けられた通貨がエスクローに預託されます。

エスクローを成立させる条件として指定可能な項目は次の2つであり、どちらか一方の項目の利用、両方の項目の利用で3パターンの条件が設定できます。

  • FinishAfter: この項目に指定した時間の経過後、エスクローのリリースが可能になります。
  • Condition: この項目に指定したCrypto-conditionに対する正しいフルフィルメントを提供した場合、エスクローのリリースが可能になります。

また、エスクローをキャンセルする条件として次の項目が指定可能です。

  • CancelAfter: この項目に指定した時間の経過後、エスクローはキャンセル可能になります。

https://xrpl.org/ja/escrowcreate.html

EscrowCancel

エスクローをキャンセルするためのトランザクションです。このトランザクションで指定するパラメータには、キャンセルするエスクローのアドレスが含まれます。このトランザクションを実行することで、預けられた通貨が返還されます。

EscrowCreateトランザクションでCancelAfterを指定しており、かつCancelAfterで指定した時刻より後である場合のみエスクローのキャンセルが行えます。

https://xrpl.org/ja/escrowcancel.html

EscrowFinish

エスクローから通貨を送金するためのトランザクションです。このトランザクションで指定するパラメータには、エスクローの作成者アドレス、エスクローを作成したシーケンス番号などが含まれます。このトランザクションを実行することで、エスクローに預託された通貨が返還されます。

エスクローにConditionが設定されている場合は、それに対する正しいFulfillmentを提供する必要があり、対応しない値が含まれていた場合はエラーとなります。
また、FinishAfterが指定されている場合に、FinishAfterに指定した時刻より前の場合も失敗します。

https://xrpl.org/ja/escrowfinish.html#escrowfinish

エスクロー機能のサンプルコード

以下は、条件に基づくエスクローを実装するためのサンプルコードです。このコードは、xrpl.jsを使用しています。

https://github.com/XRPLF/xrpl.js

https://www.npmjs.com/package/xrpl

準備

EscrowCreateトランザクションに指定するConditionの値とEscrowFinish時に使用する対応するFulfillmentの値を作成します。

const cc = require('five-bells-condition')
import crypto from 'crypto'

const preimageData = crypto.randomBytes(32)
const myFulfillment = new cc.PreimageSha256()
myFulfillment.setPreimage(preimageData)

const condition = myFulfillment.getConditionBinary().toString('hex').toUpperCase()
console.log('Condition:', condition)

const fulfillment = myFulfillment.serializeBinary().toString('hex').toUpperCase()
console.log('Fulfillment:', fulfillment)

EscrowCreate

import {
  Client,
  EscrowCreate,
  isoTimeToRippleTime,
  Wallet,
  xrpToDrops,
} from "xrpl";

const client = new Client("wss://testnet.xrpl-labs.com");

const senderWallet = Wallet.fromSeed("sEd7YTXBPGznwig7HDccWuCJniBcJJa");
// raLKKuLCZPsZuPZCEy6LhtRH3UamQ6kaHK

await client.connect();

const escrowCreate: EscrowCreate = {
  TransactionType: "EscrowCreate",
  Account: "raLKKuLCZPsZuPZCEy6LhtRH3UamQ6kaHK",
  Destination: "rGFJLzA7J7HouwYPfQb88EX61AAi2BYPjo",
  Amount: xrpToDrops(100),
  CancelAfter: isoTimeToRippleTime("2023-04-01T00:00:00Z"),
  Condition: condition,
};

const responseCreate = await client.submitAndWait(escrowCreate, {
  wallet: senderWallet,
});

console.log("Created escrow:", responseCreate.result.hash);

エスクローの作成後はエスクローの宛先人に対してエスクローが正しく作成されたことを証明する必要があるでしょう。
例えばトランザクションIDを通知することで宛先人に対するエスクローが作成されていることが確認ができます。

EscrowFinish

エスクロー送信者からFulfillmentの値を受け取ったらEscrowFinishトランザクションでエスクローをリリースし、送金を確定させることができます。

import { Client, EscrowFinish, Wallet   } from "xrpl";

const client = new Client("wss://testnet.xrpl-labs.com");
const receiverWallet = Wallet.fromSeed("sEdSjhhqsFcwvJbcTKXjCDHFCScxwnp");
// rGFJLzA7J7HouwYPfQb88EX61AAi2BYPjo

await client.connect();

// Sequenceの取得
const txResponse = await client.request({
  command: "tx",
  transaction: responseCreate.result.hash,
});

const escrowFinish: EscrowFinish = {
  TransactionType: "EscrowFinish",
  Account: "rGFJLzA7J7HouwYPfQb88EX61AAi2BYPjo",
  Owner: "raLKKuLCZPsZuPZCEy6LhtRH3UamQ6kaHK",
  OfferSequence: txResponse.result.Sequence!,
  Condition: condition,
  Fulfillment: fulfillment,
  Fee: '500'
};
const responseFinish = await client.submitAndWait(escrowFinish, {
  wallet: receiverWallet,
});

console.log("Finished escrow:", responseFinish.result.hash);

条件付きエスクローではフルフィルメントの検証に高い処理負荷がかかるため通常のトランザクションよりも若干高額なトランザクションコストを支払う必要があります。

https://xrpl.org/ja/escrow.html#escrowfinishトランザクションのコスト

まとめ

XRP Ledgerのエスクロー機能は、XRPL自体が第三者としての役割を果たし、取引の安全性を高めるために利用されます。また、このエスクローはInterledger Protocolでの送金にも利用することができ、今後より利用されることが期待されています。

PathFindに関するコードは以下のリポジトリから参照できます。
https://github.com/develoQ/xrpl-sample/blob/main/samples/escrow

興味を持たれた方はXRP Ledger開発者のDiscordチャンネルへ是非お越しください!
日本語チャンネルもありますので、英語ができなくても大丈夫です!
https://xrpldevs.org

Discussion