PumaPay プル型決済プロトコルとスマート・コントラクトを詳しく知る

PumaPay は、 Ethereum ベースの単一および定期継続支払いを含むソリューション バージョン 2.0 をリリースしました。  スマート・コントラクトの細部を覗いてみたいという好奇心をお持ちであれば、その答えは本稿の中にあります。  PumaPay のソリューションは、あらゆる種類の事業主プラットフォームと容易に統合できるオープンソースのプロトコルです。  本稿では、 PumaPay プル型決済プロトコルを統制するスマート・コントラクトの技術的細部をお見せします。

開発

スマート・コントラクトは Solidity 言語で書かれており、 Truffle と Ganache-cli を使ってテストされています。これらはすべて Open Zepellin によって開発されたモジュールに基づいています。

PumaPay トークン

PumaPay トークンは ERC-20 トークン規格 に基づいており、2018年5月7日に催された TGE (トークン・ジェネレーション・イベント)において Ethereum ネットワークに展開されました。

使用法 

契約が展開されたアドレスが所有者アドレスとして設定されます。  所有者だけが mint() メソッドと finishMinting() メソッドを呼び出すことができます( Mint = 英語で鋳造)。
Minting (鋳造)は累積的です。  このメソッドを同じアドレスに対して2回呼び出すと( Mint 値が 0 より大きい場合)、そのアドレスの残高が上昇します。
所有者が finishMinting() を呼び出すまで、トークンは譲渡できません。
finishMinting() が呼び出されると、それを元に戻すことはできません。つまり、新しいトークンを増やすことはできません。
ETH アドレス:0x846c66cf71c43f80403b51fe3906b3599d63336f
トークン総額:78,042,956,829 PMA – 流通供給額:15,942,078,847 PMA

プル型決済コントラクト 

このプロトコルの革新的な機能の1つは、ユーザーが別のユーザーの財布にウォレットを投入するのではなく、他のウォレットから資金を引き出すことができるということです。この点で、 PumaPay は暗号通貨支払いの仕組みを逆転させて、事業主による「プル」型決済の主導を容易にし、最初に顧客からの承認を得た上で、顧客のウォレットから請求金額を引き出せるようにします 。もちろん、事業主に多大な手数料が課されることはありません。

コントラクト設定 

コントラクトが発動するトークンアドレスを設定します。

constructor (PumaPayToken _token)

 

支払い

PumaPay プル型決済コントラクトが所有者/決済者の資金調達を可能とする ETH を受け取ることを許可します。

function () external payable 

 

メンバー

所有者

PumaPay プル型決済コントラクト契約は所有可能です。

contract PumaPayPullPayment is Ownable 

スマート・コントラクトの所有者は特定の 1 名に設定され以下の責任を負います:

  1. PMA / Fiat レート機能の設定 setRate(string _currency、uint256 _rate)
  1. 決済者機能を追加する function addExecutor(address _executor)
  1. 決済者機能を削除する removeExecutor(address _executor)
    決済者を追加または削除することに関連する各機能において、所有者の残高はチェックされ、残高が 0.01 ETH 未満であれば、決済に関連するガス費用を支払うために 1 ETH がオーナーアドレスに送信される 。
    所有者は、スマート・コントラクトを管理する共同体が統制するアドレスです。
if (isFundingNeeded(owner)) {    owner.transfer(1 ether);} 

 

決済者

PumaPay プル型決済コントラクトには、複数の決済者を含めることができます。

各決済者は、顧客に代わってプル型決済を登録または取り消すことができます。  顧客はウォレットを介して keccak256 を使用しプル型決済の詳細に署名する必要があります。また、登録または取り消しには、署名付きプル型決済の署名パラメータ(v、r、s)を使用して、顧客アドレスが実際に登録または キャンセルを申請したものであることを認証します。  登録または取消し時に決済者の残高がチェックされ、 0.01 ETH より低い場合は、スマート・コントラクトから決済者に ETH が送信され、プル型決済の登録または取消が許可されます。
決済者は、スマート・コントラクトを統制する共同体が所有するアドレスです。

mapping (address => bool) public executors; 

 

プル型決済

PumaPay プル型決済コントラクトは、プル型決済の 2 つのアドレスで構成されています。  最初のアドレスは顧客アドレスであり、 2 番目のアドレスは事業主アドレスです。

mapping (address => mapping (address => PullPayment)) public pullPayments; 

プル型決済の構造形態は以下の通りです。

struct PullPayment { 
     string merchantID; /// ID of the merchant 
     string paymentID; /// ID of the payment 
     string currency; /// 3-letter abbr i.e. 'EUR' / 'USD' etc. 
     uint256 initialPaymentAmountInCents; /// initial payment amount in fiat in cents 
     uint256 fiatAmountInCents; /// payment amount in fiat in cents 
     uint256 frequency; /// how often merchant can pull - in seconds
     uint256 numberOfPayments; /// amount of pull payments merchant can make 
     uint256 startTimestamp; /// when subscription starts - in seconds 
     uint256 nextPaymentTimestamp; /// timestamp of next payment 
     uint256 lastPaymentTimestamp; /// timestamp of last payment 
     uint256 cancelTimestamp; /// timestamp the payment was cancelled 
} 

定数

uint256 constant private DECIMAL_FIXER = 10000000000; // 1e^10 - This transforms the Rate from decimals to uint256
uint256 constant private FIAT_TO_CENT_FIXER = 100;    // Fiat currencies have 100 cents in 1 basic monetary unit.
uint256 constant private ONE_ETHER = 1 ether;         // PumaPay token has 18 decimals - same as one ETHER
uint256 constant private MINIMUM_AMOUN_OF_ETH_FOR_OPARATORS = 0.01 ether; // minimum amount of ETHER the owner/executor should have

addExecutor() 

既存の決済者を追加します。  これは所有者によってのみ実行することができます。
所有者の残高が確認され、資金が必要な場合は ETH が転送されます。

function addExecutor(address _executor) 

removeExecutor() 

既存の決済者を削除します。  これは所有者によってのみ実行することができます。
所有者の残高が確認され、資金が必要な場合は ETH が転送されます。

function removeExecutor(address _executor) 

setRate() 

通貨の為替レートを設定します。  これは所有者によってのみ実行することができます。
所有者の残高が確認され、資金が必要な場合は ETH が転送されます。

function setRate(string _currency, uint256 _rate) 

パブリック関数決済者

registerPullPayment() 

PumaPay プル型決済コントラクトに新しいプル型決済を登録します。  登録は、 PumaPay プル型決済コントラクトの決済者の 1 人によってのみ実行され、 PumaPay プル型決済コントラクトは、プル型支払いがアカウントのクライアントによって署名されたことを確認します。  決済者 (msg.sender) の残高がチェックされ、資金調達が必要な場合は 1 ETH が転送されます。

function registerPullPayment (
     uint8 v,        
     bytes32 r,        
     bytes32 s,        
     string _merchantID,        
     string _paymentID,        
     address _client,        
     address _beneficiary,        
     string _currency,        
     uint256 _initialPaymentAmountInCents,        
     uint256 _fiatAmountInCents,        
     uint256 _frequency,        
     uint256 _numberOfPayments,        
     uint256 _startTimestamp    
) 

deletePullPayment() 

受益者のプル型決済を削除します。  この削除は、 PumaPay プル型決済コントラクトの決済者の 1 人によってのみ実行され、 PumaPay プル型決済コントラクトは、受取人および paymentID がアカウントを持つクライアントによって署名されたことをチェックします。  このメソッドは、指定された受益者のプル型決済コントラクトのキャンセルをプル型決済アレイに設定します。  決済者 (msg.sender) の残高がチェックされ、資金が必要な場合は 1 ETH が転送されます。

function deletePullPayment (
     uint8 v,        
     bytes32 r,        
     bytes32 s,        
     string _paymentID,        
     address _client,        
     address _beneficiary    
) 

パブリック関数

executePullPayment() 

Msg.sender 関数を呼び出すアドレスのプル型決済を実行します。プル型決済が存在する必要があり、支払請求が実行可能な時点で有効である必要があります。

  • 利用ケース 1:単一/定期継続固定支払 (initialPaymentAmountInCents == 0)
    PMA の金額は、プル型決済で指定された通貨のレートと fiatAmountInCents を使用して計算され、クライアントのアカウントから PMA での金額を送金します。実行後、最後の支払いタイムスタンプを NOW に設定し、次の支払いタイムスタンプは頻度によって増加される一方、支払い回数そのものは 1 回分減少します。
  • 利用ケース 2:手数料付きの定期継続固定プル型決済 (InitialPaymentAmountInCents> 0)
    PMA の金額は、プル型決済で指定された通貨のレートと  ‘initialPaymentAmountInCents’ を使用して計算し、クライアントのアカウントから PMA での金額を送金します。実行後、最後の支払いタイムスタンプを NOW に設定し、 initialPaymentAmountInCents をゼロに設定します

内部関数

isValidRegistration() 

v、r、s パラメータとハッシュされたパラメータをクライアントのものと比較して登録要求が有効かどうかをチェックします。  ハッシュされたパラメータは、受益者(事業主)のアドレス、通貨、 initialPaymentAmountInCents 、 fiatAmountInCents 、頻度、 numberOfPayments および startTimestamp です。

ecrecover(    
     keccak256(        
          abi.encodePacked(            
          _beneficiary,            
          _pullPayment.currency,            
          _pullPayment.initialPaymentAmountInCents,            
          _pullPayment.fiatAmountInCents,            
          _pullPayment.frequency,            
          _pullPayment.numberOfPayments,            
          _pullPayment.startTimestamp        
)), v, r, s) == _client; 

ETH署名とECDSA署名のリカバリIDの詳細は、 こちらを参照してください。


isValidDeletion() 

v、r、s パラメーターと顧客ハッシュパラメーターと比較して、削除要求が有効かどうかを精査します。 アドレスと paymentID 自体も同様です。  ハッシュされたパラメータは、 paymentID と受益者(事業主)のアドレスです。

ecrecover(    
     keccak256(        
           abi.encodePacked(            
           _paymentID,            
           _beneficiary        
)), v, r, s) == _client && 
keccak256(abi.encodePacked(pullPayments[_client][_beneficiary].paymentID)) == keccak256(abi.encodePacked(_paymentID)); 

calculatePMAFromFiat() 

指定された金額通貨の PMA レートを計算します。  このレートは、スマート・コントラクトで指定された通貨について PMA サーバーが10分ごとに設定します。  2つのヘルパー/フィクサーがこの計算に使用されます:

  1. ONE_ETHER – WEIにおける 1 ETH の値を実行する 1e18
  1. DECIMAL_FIXER – Rate を decint から uint256 に変換し、レートの設定に使用されているのと同じ値となります。

FIAT_TO_CENT_FIXER – スマート・コントラクトで使用されている支払い金額は、小数点以下がまだサポートされていないため、 CENTS に記載されています。


doesPaymentExist() 

クライアントの受益者(事業主)の支払いが存在するかどうかをチェックします。


isFundingNeeded() 

所有者または決済者のアドレスに資金が必要かどうかをチェックします。所有者または決済者が常に最低限必要とする金額は 0.01 ETH です。


イベント

event LogExecutorAdded(address executor);       // When adding a new executor
event LogExecutorRemoved(address executor);     // When removing an existing executor
event LogPaymentRegistered(address clientAddress, address beneficiaryAddress, string paymentID);    // When registering a new pull payment
event LogPaymentCancelled(address clientAddress, address beneficiaryAddress, string paymentID);     // When removing a new pull payment
event LogPullPaymentExecuted(address clientAddress, address beneficiaryAddress, string paymentID);  // When executing a pull payment
event LogSetExchangeRate(string currency, uint256 exchangeRate);        // When updating the PMA/FIAT rates 
0.00 avg. rating (0% score) - 0 votes

    No Comment.