1.0.1 • Published 6 years ago

@zeex/zeex-contracts v1.0.1

Weekly downloads
-
License
ISC
Repository
github
Last release
6 years ago

Zeex Contracts

This repository includes all the contracts that together form the Zeex Protocol. This document describes how to use them - as a supplier and as an application designed for buyers.

General

The way the Zeex Protocol operates is explained in details in Zeex Whitepaper. To briefly summarize, the process in comprised of a few steps:

  • A supplier uploads inventory to the smart contract
  • A user can view the available inventory and decide to purchase voucher(s)
  • The purchase transaction is a two step transaction:
    • First the user purchases specific voucher(s). At the end of the transaction the vouchers are allocated to the user, but he cannot see their private information, i.e. serial and cvv
    • A swapper process which runs in the background captures the purchase and encrypts the voucher's private information with the buyer's public key so only the buyer can read it

We'll explore the functionality from both the supplier and the buyer perspectives.

Contracts

There are four smart contracts that should be used to access all the functionality required by the suppliers as well as the buyer:

  • ZeexInventoryBasicProtocol.sol
  • ZeexInventoryProtocol.sol
  • ZeexPurchaseProtocol.sol
  • ZeexSupplierProtocol.sol
  • ZeexEvents.sol

All the events emitted from every operation are emitted from the ZeexEvents contract. We'll link to the relevant protocol at the right places.

Buyer


As mentioned above, the buyer first reviews the available inventory and then makes a purchase. The following section provides an overview of the relevant functions.

At the smart contract ZeexInventoryBasicProtocol.sol you can find the following functions:

function getBrands() public view returns (bytes32[]); // Get the available brands

function getBrandCurrencySymbols(bytes32 _brand) public view returns (bytes3[]); // Get the available currency symbols for the specific brand, e.g. GBP, USD, etc.

function getFaceValues(bytes32 _brand, bytes3 _currencySymbol) public view returns (uint[]); // Get the face values supported by this brand and currency symbols, e.g. 25, 50, 100 etc.

At this point, you can check the inventory status using this function from ZeexInventoryProtocol.sol:

function getVouchersCount(
    bytes32 _brand,
    bytes3 _currencySymbol,
    uint _faceValue
  )
    public
    view
    returns (
      uint count
    );

This function will return the available count of vouchers for the brand, currency symbol and face value specified in the parameters.

At this point, you can make a purchase for voucher(s) using functions from ZeexPurchaseProtocol.sol. The first thing you need to find out is the purchase cost. For example, if you wish to purchase vouchers worth of 50 GBP, you need to know how much Ether you need to pay for them. In order to do that, call the following function:

function getPurchaseCost(
    bytes3 _currencySymbol,
    uint _amount
  )
    public
    view
    returns (
      uint totalCost,
      uint baseCost
    );

For example, pass 'GBP' and 50. The function returns the totalCost which is the amount you need to pay for the vouchers. The baseCost is the cost for the vouchers without including additional fees such as the swapper fee. You should not use this value.

In order to purchase, you have a few options:

function purchase(
    bytes32 _brand,
    bytes3 _currencySymbol,
    uint _amount,
    string _encryptionKey
  )
    public
    payable
    returns (
      uint purchaseId
    );

This function accepts the brand and currency symbol you wish to purchase as well as the amount. The _encryptionKey is the buyer's public key which will be used to encrypt the vouchers' private data (serial and cvv). For example:

purchase('Some Brand', 'USD', 100, 'Some encryption key');

At the end of the purchase transaction, ZeexEvents contract will emit the following event:

event Requested(uint indexed purchaseId);

The purchase id is the id of this specific purchase which will be used later.

Alternatively, you can use other purchase functions:

function purchaseFaceValue(
    bytes32 _brand,
    bytes3 _currencySymbol,
    uint _faceValue,
    uint _count,
    string _encryptionKey
  )
    public
    payable
    returns (
      uint purchaseId
    );

In this function you pass the specific face value you wish to purchase, e.g. 50 and how many vouchers you want from this face value. For example:

purchaseFaceValue('Some Brand', 'USD', 50, 4, 'Some encryption key');

In this example, the buyer requests 4 $50 vouchers of brand 'Some Brand', i.e. $200 worth of vouchers.

You can also use this function:

function purchaseFaceValues(
    bytes32 _brand,
    bytes3 _currencySymbol,
    uint[] _faceValues,
    string _encryptionKey
  )
    public
    payable
    returns (
      uint purchaseId
    );

In this function you specify the specific face values you wish to purchase. For example, 25, 50, 100 or event 25, 25, 50.

purchaseFaceValues('Some Brand', 'USD', [25, 50, 100], 'Some encryption key');

purchaseFaceValues('Some Brand', 'USD', [25, 25, 50], 'Some encryption key');

Aftter the purchase completes, a swapper process fulfills the purchase. In this process, it takes the requested vouchers and re-encrypts their private information with the buyer public key, so later they can be decrypted by the buyer. When it finishes, it emits the event

event Fulfill(uint purchaseId);

to indicate that the specific purchase has been fulfilled.

In case you missed the event, or if you wish to obtain all buyer's purchases, you can use the function

function getBuyerPurchases(address _buyer) public view returns (uint[]);

to obtain the list of purchases of a specific buyer. The returned value from this function is an array of purchase ids. You can then use the following function to obtain the purchase information:

function getPurchase(uint _id)
    public
    view
    returns (
      bytes1 status,
      address buyer,
      bytes32 brand,
      bytes3 currencySymbol,
      uint[] voucherIds,
      uint totalCost,      
      address[] suppliers,
      uint[] suppliersPendingAmountToPay,
      bytes reEncrypted
    );

This information returned from this function includes:

  • status - the possible values are: P for pending transaction, F - for fulfilled transaction and R - for refunded transaction. You should mainly care about transactions whose status is P
  • buyer - the address of the buyer
  • brand the brand of all vouchers in this purchase
  • currencySymbol - the currency symbol of all vouchers in this purchase. The symbol is a 3 letter code according to ISO 4217
  • voucherIds - an array containing all the vouhcer ids of all vouchers in this purchase. While you can obtain the vouchers information from this array, it is not necessary
  • totalCost - the total cost of this purchase in Ether
  • suppliers - used internally
  • reEncrypted - this is an encrypted bytes of all serial number and cvv for all the vouchers in this purchase. The encryption is done with the buyer's public key so the buyer can later decrypt it. This field includes the serial / cvv of all vouchers purchased in this specific transaction. The serial is separated by comma (,) from the cvv, while pair of serial / cvv are separated by | character. Note that this parameter will be empty as long as the purchase status is Pending and will hold the vouchers data only when the status is Fulfilled

Supplier


Before uploading inventory a supplier has to be approved by Zeex. After he has done that, they can use the functionality from ZeexInventoryProtocol.sol. From the supplier perspective, the main function is:

function restock(
    bytes32 _brand,
    bytes3[] _currencySymbols,
    uint[] _faceValues,
    uint[] _expiries,
    bytes _encryptedCodes,
    uint[] _chunks
  )
    public;

This function restocks several vouchers for a specific brand. It accepts 3 lists:

The serial and cvv information should be passed in as bytes where the chunks determines the length of each serial / cvv pair. For example, serial1cvv1serial2cvv2serial333cvv333. These bytes should be encrypted with the swapper's public key. Later, they will be decrypted and encrypted with the buyer's public key. The chunks for this specific example should be 11, 13, 15 since the length of 'serial1cvv1' = 11 and the length of 'serial22cvv22' = 13, 'serial333cvv333' = 15.