Develop a Marketplace Contract with Token Payment

KC Tam
Coinmonks
11 min readMay 19, 2019

--

Introduction

In my previous article (link) I have shown the use of dapps.tools in Ethereum contract development, and see how to use dapp and seth to perform unit testing of contract code with a testset, and deploy my contract code in a local testnet.

In this article I first create another contract simulating a marketplace. And deployment I will add a token as the payment for items in the marketplace. The token I am using is from ds-token package, which is a mintable ERC20 token. Finally we will demonstrate the execution of contract functions and see how my contract interacts with the token contract.

Overview of the Application

The application is a smart contract simulating a marketplace operation. It keeps items listed by someone (seller) at a price tag, and another (buyer) can buy the item by paying that price to the seller. It also comes with some checking functions to see if that item exists or is already sold. Meanwhile the buyer can remove the item from the marketplace provided that the item is not sold to anyone yet.

In phase 1 we will complete these functions. In phase 2, we will implement an ERC20 token as the (only) payment method in this marketplace.

This application itself by no means a complete one for production, and there are still many to do for tuning and optimization before it is a full function. Nevertheless, this fulfils my purpose to show how to use dapp.tools to build something interesting and add a token using ds-token package.

A marketplace application with token payment

Phase 1: Marketplace without Token Payment

Create a Workspace for this contract. We name the workspace as emarket (directory name). With dapp.tools we will have a predefined contract name Emarket.sol and the associated testing contract Emarket.t.sol.

We will look into the two contract files. Then begin to test and deploy the contract on testnet. Finally we will simulate some activities over this deployed contract.

Contract: Emarket.sol

Here is the contract code I am using in this demonstration.

The data structure Item keeps the detail of each item posted in the emarket. It contains a description, the seller and the buyer, price, and a boolean whether this item is sold or not. Note that the price is just a number at this stage, and later it will be an amount of token after we implement the token in phase 2.

The items is the mapping from an index to the data structure Item. We simply maintain a counter itemCount for counting index.

No constructor is needed in this contract. Six functions are defined in this contract.

addItem(description, price) is called when a seller lists an item in the emarket. What we need are just a description and the price of that item. This will be recorded as a new item indexed with itemCount+1.

getItem(index) is called when anyone wishes to show detail about an item. We will get back the description and price.

checkedItemExisting(index) is called when anyone wishes to know whether an item exists or not.

checkedItemSold(index) is called when anyone wishes to know whether an item has already been sold.

removedItem(index) can only be called by the seller who lists the item before.

buyItem(index) is called by a buyer. Buyer can only buy item if it is not sold yet. Currently the logic simply updates the buyer address and marks the sold flag.

Test Contract: Emarket.t.sol

We have defined four test cases for my emarket contract. They are quite self-explanatory so here we do not provide the detail.

Setup Workspace

We will have setup our workspace emarket as shown the previous article.

After we paste our contract Emarket.sol and the test contract Emarket.t.sol, we can perform the unit test using dapp test.

And from the result we know all test cases are passed.

Run Testnet and Deploy the Contract

As before, we open another terminal to run a testnet, using dapp testnet. To get two more addresses for demonstration, we can can specify option -- account.

We will create the environment variables for demonstration purpose. The first one we use ETH_FROM such that it is the coinbase account. If we do not specify anything it is the default account.

And we deploy the contract using dapp create.

Now we have the contract address 0x7e2d…d237. As good practice we use an environment variable to keep this address.

Interacting with the Contract

In this demo we simulate a real life example. This involves the following steps.

  1. Check currently no items are in the marketplace yet.
  2. Alice lists an item “a pen” and marks the price 100. Check that the item is in marketplace.
  3. Bob buys this item. Check that this item is sold and Bob’s address is correctly recorded.
  4. Alice tries to remove this item but fails, as this item is already sold.

Step 1: First let’s see the current itemCount.

Step 2: Alice lists an item.

Then take a look on the itemCount and item #1 detail.

We can see there is one item, and we see the description (“a pen” in ascii), seller Alice, and this item not sold yet.

Step 3: Now Bob buys this item (item #1).

And after that we check item #1 again.

Now we see the buyer address (Bob’s) recorded, and this item is marked as true (sold).

Step 4: Alice tries to remove this item. She cannot as this item was sold already.

Phase 2: Marketplace with Token as Payment Methods

Create a New Workspace

With the basic functions of marketplace ready, we will now include an ERC20 token as the pricing and payment method for this marketplace.

To keep things neat, here we create another workspace, namely emarketwithcoin

We are using ds-token package provided in dapp.tools. ds-token is a package of standard ERC20 implementation, plus some additional functions like mint() and burn(). There are some advanced features working with other packages but the basic ERC20 and the mint/burn are good enough for our demonstration.

We will first install the package.

All the required packages required are installed. The package is installed under lib/ds-token.

If we inspect the token contracts in lib/ds-token/src/base.sol and lib/ds-token/src/token.sol, we probably see an implementation of ERC20 tokens, and some additional functions. Meanwhile each comes with a unit test contract, and the test are running when the contract is deployed.

Modify Our Contract Code

For simplicity, we only focus on the contract code, and put aside the testing contract code (we see how it works in early sessions). It is not the best practice as we should always use testing contract for unit testing. Nevertheless, we assume our code are good for demonstration.

Here is the contract code for Emarketwithcoin.

Here I just highlight the additional portion on top of the previous example.

1. Import the contract from the ds-token package. Here we import token.sol.

If we take a look on the code, token.sol further imports base.sol. And token.sol provides the class DSToken that we will use later. Note the default DSToken comes without a fixed supply and with decimal precision 18. For demonstration purpose we will keep this without considering the actual precision.

2. Specify where the token contract is.

Here we define an object emark, which holds the deployed token contract. As a result, in our deployment we first deploy a token contract, and the contract ID of the deployed contract is passed to this contract through constructor. We will see how it works later.

3. Transfer tokens when buy an item.

We add two logics here. First we will check buyer’s balance when he buys a listed item. If balance is not enough the transaction fails. Also we will use transferFrom to transfer tokens from someone who buys this item to the seller of this item. Since it is the Emarketwithcoin contract performs the transferFrom, the buyer needs to approve the Emarketwithcoin contract for the transfer. We will see how it works later.

4. Update the test contract (inside Emarketwithcoin.t.sol).

As we have included constructor and an address is required, we need to modify the Emarketwithcoin.t.sol with a pseudo address for getting through the test. Again we are not defining any test cases and therefore the test address is not meaningful in this case.

Deploy Contracts in Testnet

Token contract is deployed first as Marketplace requires the Token Contract ID

As before, we open another terminal to run a testnet, using dapp testnet. We also needs two more addresses for demonstration.

We will create the environment variables for demonstration purpose. The first one we use ETH_FROM such that it is the coinbase account. If we do not specify anything it is the default account.

Now we deploy the token contract first. The symbol we pass to the new contract is emark.

Now we have the token contract ID (or contract address). We will use an environment variable EMK to hold this address.

With this, we can deploy the Emarketwithcoin contract. We specify the token contract ID as required in constructor.

Now we have another contract ID. We will hold this in environment variable MARKET.

Now we have both contracts deployed.

Interacting with the Contracts

Our demonstration flow on these deployed contract is simple.

  1. Check emark balance of both Alice and Bob, and see no balance at the beginning.
  2. Mint Bob 100 emarks. It will be used for buying an item listed by Alice.
  3. Alice lists an item with price set to 80 emarks.
  4. Bob buys this item.
  5. Check emark balance of both Alice and Bob, and we see 80 emarks transferred to Alice.

Always remember we have two contracts: EMK for token, and MARKET for marketplace. They are two independent contracts, and the only linkage is that MARKET contract will call EMK when someone buys items.

Step 1: We begin with token contract. Check balance of total EMK supply, and balances of Alice and Bob.

Initially all are zero. No emark exists yet.

Step 2: We mint 100 emarks to Bob.

And check the balance. Bob has 100 emarks (0x64) and total emark supply is also 100.

Before MARKET can transfer tokens from Bob’s account, Bob needs to approve MARKET that amount. Assuming Bob approves 80 emarks.

Step 3: We move to the marketplace. Alice lists an item “a pen” and the price is 80 emarks.

And we will see the item #1 recorded.

Item is listed by Alice and now sold yet.

Step 4: Bob is buying this item.

And we check the item #1 again.

The item is sold to Bob.

Step 5: Finally we check the total EMK supply and balance of both Alice and Bob again.

We see 80 emarks is transferred from Bob to Alice as Bob has bought Alice’s item with 80 emarks. And the total supply remains 100 emarks.

Closing

We have shown a sample marketplace contract (again, not optimized one and not for production). We saw how to use test contract to implement some unit tests on the functions. After deploying on the testnet, we demonstrate how to execute the functions defined in the marketplace. Then we use the same marketplace contract and add token as the pricing and payment method. Using ds-token package and with a few modifications, the marketplace contract can perform the token transfer when a buying is made.

Hope you can see the use of dapp.tools and the convenience when developing contract on Ethereum platform. There are some other packages from dapp.tools and you will find more fun from them.

Get Best Software Deals Directly In Your Inbox

--

--