最終更新:
編集

Partial Payment

デフォルトのケースでは、XRP LedgerのPaymentトランザクションAmountフィールドに、為替レートと送金手数料を差し引いた実際の送金額が指定されます。「Partial Payment」フラグ(tfPartialPayment)を使うと、送金額を増額する代わりに受取金額を減額して、支払を正常に実行できます。Partial Paymentは、追加コストなしで支払を返金したい場合に便利です。

トランザクションコストに使用されるXRPの額は、トランザクションタイプに関わらず常に送金元のアカウントから差し引かれます。

Partial Paymentは、XRP Ledgerとのネイティブ統合を悪用して取引所およびゲートウェイから資金を盗むのに使用される恐れがあります。本書のPartial Paymentの悪用セクションで、この悪用の仕組みと防止対策を説明します。

セマンティクス

Partial Paymentを使用しない場合

Partial Paymentフラグを使用しないで送金する場合、トランザクションのAmountフィールドに実際の送金額を指定し、SendMaxフィールドに送金上限額と通貨を指定します。Amountの額を全額送金するとSendMaxパラメーターの値を超えてしまう場合や、その他何らかの理由で総額を送金できない場合は、トランザクションは失敗します。トランザクション指示でSendMaxフィールドが省略されると、Amountと同額とみなされます。この場合、手数料の合計が0である場合のみ支払が成功します。

つまり、次の式になります。

Amount+(手数料)=(送金額)≤ SendMax

この式の「手数料」は、送金手数料と通貨の為替レートを指します。送金額(Amount)の通貨は、送金側と受取側で異なる通貨建てにすることができ、XRP Ledgerの分散型取引所でオファーを消費することにより交換されます。

注記: トランザクションのFeeフィールドが参照するXRPトランザクションコストは、トランザクションをネットワークに中継するために消却されます。トランザクションコストは、常に指定通りの額が送金元から引き落とされ、あらゆるタイプの支払の手数料計算とは完全に切り離されています。

Partial Paymentを使用する場合

Partial Paymentフラグが有効になっている支払を送金する場合、このトランザクションのAmountフィールドには送金限度額を指定します。Partial Paymentでは、制限(手数料、流動性不足、受取アカウントのトラストラインの枠不足など)の有無にかかわらず、指定額の 一部 を送金できます。

オプションのDeliverMinフィールドには、送金下限額を指定します。SendMaxフィールドは、Partial Payment以外で送金する場合と同様に機能します。Partial Paymentトランザクションは、送金額がDeliverMinフィールドの金額以上、SendMaxの金額未満であれば成功します。DeliverMinフィールドに指定のない場合、任意の正の金額の送金であれば、Partial Paymentは成功します。

つまり、次の式になります。

金額 ≥(送金額)= SendMax -(手数料)≥ DeliverMin > 0

Partial Paymentの制限事項

Partial Paymentには次の制限事項があります。

  • Partial Paymentでは、アドレスにXRPにて資金を供給できません。この場合、結果コードtelNO_DST_PARTIALが返されます。
  • Partial Paymentでは、XRP間の直接決済はできません。この場合、結果コードtemBAD_SEND_XRP_PARTIALが返されます。
    • ただし、イシュアンスからXRPへの支払またはXRPからイシュアンスへの支払は、Partial Paymentが可能です。

delivered_amountフィールド

Partial Paymentでの実際の送金額を把握できるように、正常に完了したPaymentトランザクションのメタデータにはdelivered_amountフィールドが含まれています。このフィールドには送金額がAmountフィールドと同じフォーマットで示されています。

Partial Payment以外の場合、トランザクションのメタデータのdelivered_amountフィールドは、トランザクションのAmountフィールドと同じです。支払がトークンで行われた場合、丸め方によりdelivered_amountAmountフィールドとやや異なることがあります。

次の両方の条件に該当するトランザクションでは、送金額を使用できません

  • Partial Paymentである
  • 2014-01-20以前の検証済みレジャーに含まれている

この両方の条件に該当する場合、delivered_amountには実際の金額ではなく文字列値unavailableが示されます。この状況で実際の送金額を確認する唯一の方法は、トランザクションのメタデータでAffectedNodesを参照することです。トークンを送金するトランザクションで、AmountissuerDestinationアドレスと同じアカウントである場合、送金額は異なる取引相手へのトラストラインを表す複数のAffectedNodesメンバー間で分割できます。

delivered_amountフィールドは以下のフィールドに含まれています。

APIメソッドフィールド
JSON-RPC / WebSocketaccount_txメソッドresult.transactions 配列メンバーの meta.delivered_amount
JSON-RPC / WebSockettxメソッドresult.meta.delivered_amount
JSON-RPC / WebSockettransaction_entryメソッドresult.metadata.delivered_amount
JSON-RPC / WebSocketledgerメソッド(トランザクションが展開されている状態)result.ledger.transactions 配列メンバーのmetaData.delivered_amount 新規: rippled 1.2.1
WebSocketトランザクションサブスクリプションサブスクリプションメッセージのmeta.delivered_amount 新規: rippled 1.2.1
ripple-lib v1.xgetTransaction メソッドoutcome.deliveredAmount
ripple-lib v1.xgetTransactions メソッド配列メンバーの outcome.deliveredAmount

Partial Paymentの悪用

金融機関によるXRP Ledgerとの統合が、PaymentのAmountフィールドは常に総送金額であると想定して行われる場合、不正使用者がその想定を悪用して、金融機関から資金を盗むことが可能になります。Partial Paymentがゲートウェイ、取引所、または業者のソフトウェアで正しく処理されない限り、これらの機関に対してこのような悪用が行われる可能性があります。

着信Paymentトランザクションを正しく処理するには、Amountフィールドではなく delivered_amountメタデータフィールドを使用します。 これにより、金融機関が 実際の 受取金額を間違えることがなくなります。

悪用シナリオの流れ

脆弱な金融機関を攻撃するため、不正使用者は次のような操作を試みます。

  1. 不正使用者がPaymentトランザクションを金融機関に送信します。このトランザクションのAmountフィールドの額は高額で、tfPartialPaymentフラグが有効になっています。
  2. Partial Paymentは成功しますが(結果コードtesSUCCESS)、実際には指定通貨でわずかな金額だけが送金されます。
  3. 脆弱な金融機関はトランザクションのAmountフィールドを確認しますが、Flagsフィールドやdelivered_amountメタデータフィールドは確認しません。
  4. 脆弱な金融機関は、XRP Ledgerへ入金されたdelivered_amountが非常に少額のであるにもかかわらず、外部システム(金融機関独自のレジャーなど)でAmountの総額を不正使用者に入金します。
  5. 不正使用者は、脆弱な機関がこの差異に気付く前に、可能な限りの多くの残高を別のシステムに出金します。
    • ブロックチェーントランザクションは通常不可逆であるため、不正使用者は一般的にBitcoinなどの他の仮想通貨に残高を換金することを好みます。法定通貨システムに出金した場合、金融機関がトランザクションを撤回または取り消せるのは、最初にトランザクションが実行されてから数日後になります。
    • 取引所の場合、不正使用者はXRPから残高を出金し、直接XRP Ledgerに戻すこともできます。

業者の場合、操作の順序がやや異なりますが、概念は同じです:

  1. 不正使用者が大量の商品やサービスの購入を依頼します。
  2. 脆弱な業者が不正使用者に対し、購入された商品やサービスの手数料を請求します。
  3. 不正使用者がPaymentトランザクションを業者に送信します。このトランザクションのAmountフィールドの額は高額で、tfPartialPaymentフラグが有効になっています。
  4. Partial Paymentが成功しますが(結果コードtesSUCCESS)、指定通貨でわずかな金額だけが送金されます。
  5. 脆弱な業者はトランザクションのAmountフィールドを確認しますが、Flagsフィールドやdelivered_amountメタデータフィールドは確認しません。
  6. 脆弱な業者は、XRP Ledgerへの入金されたdelivered_amount が非常に少額であるにもかかわらず、請求を支払済みとして扱い、商品またはサービスを不正使用者に納入します。
  7. 不正使用者は、業者が差異に気付く前に、商品やサービスを使用、再販売または持ち逃げします。

その他の緩和対策

このような悪用を防ぐには、着信トランザクションの処理でdelivered_amountフィールドを使用すれば十分です。ただし、積極的な取り組みを追加することによっても、このような悪用が発生する可能性を回避または緩和できます。例:

  • 出金処理のビジネスロジックにサニティチェックを追加します。XRP Ledgerで保有している残高の合計が、予期されている資産と債務に一致しない場合は、出金を処理をしません。
  • 「顧客確認」のガイドラインに従い、顧客の身元情報を厳密に検証します。不正使用者を事前に認識して阻止したり、システムを悪用した不正使用者に対して法的措置を講じたりすることができます。