Simple Promo Code (Coupons) for ERC20 token on Ethereum.

Artiya
5 min readJun 16, 2019

--

I am a developer of Carboneum — the social trading platform on Ethereum and having a bad experience airdropping our token for people. We spend like 10 ETH and long hours just for sending out Carboneum (C8) token for 20K addresses and unfortunately more than half of them are from the same person. Addresses were created to get our token for free and sell it for a price. The airdrop was meant to get more people aware of our service. This fails ultimately. I almost lost faith in humanity and snap my finger with the infinity stones just to hard fork the Ethereum blockchain to reverse transactions. After that, we keep the project on the timeline. My boss got a brilliant idea for sending out C8 token to people for a promotion campaign. I want to make it less hassle. My first idea was making a paper wallet, printed out and send the C8 token to it but for the receiver is not the best experience. The receiver has to import our paper wallet send some ETH to it for gas price and send the token back to their original wallet. It does less, cost more, it’s like the Apple product. I have a second thought on it. Why don't me create a smart contract and let whoever have the correct code redeem token on it? Me got no cost to send the token out. The receiver is the one pay for the operation. Sound like a good idea, It can be done.

Back on the Jan, I got a wake-up call from my boss on Saturday morning to open my office door for KatinRun 0x4 meet up, an Ethereum developer community meetup in Bankok and it happen in my office. I live really close to getting them in time. I took an opportunity to gain some knowledge from it. One of the knowledge got is how to make a voucher card and redeem system on Ethereum. At first glance, The system was too complex. It got 2 server and 2 databases. The technical debt would be deep more than our ICO fund we raised and It can DOS by sending redeem multiple requests at the same time and drain gas from transaction server even transaction fails. Thanks to my boss, he stopped me when discussing it with a developer before my blunt opinion getting louder than the speaker. I served as a photographer that day and talk to no one about it.

This time I want to design the system from scratch. I want a dead simple UX with no database, no server, just a smart contract. It could be a sign the redeem code with the issuer wallet and check the code’s signature on a smart contract. The promo code and signature can fit on a QR code link to a DApp web page for user to submitting redeem transaction. Hash collision chance is slimmer than a chance that I have a girlfriend. I don’t recommend typing the code and signature, everyone got a phone camera right?. If it got the same as issuer then just call ERC20 transferFrom function to send out the token for whoever calls the contract and keep the hash of the used code so it cannot use it again.

The script for generates promo code and it prints out with the promo code and its signature in CSV for Adobe InDesign paper voucher print. NodeJS script (Web3 1.0), No GUI because generating a promo code on DApp with MetaMask need to click on confirm box everytime each promo code sign. I simply don't want someone wasting time doing it.

Usage: nodejs GenPromoCode > OUTPUT_FOR_INDESIGN.csv

Example output:

The smart contract code looks like this. DO NOT USE THIS

At first test on Truffle, it runs flawlessly but It on the mainnet some transaction reverse for no reason. Sometimes it works, sometimes it not. I took a while to figured out that it got a front run problem. Some guy trying to send a copy of the code and its signature with a higher gas price. The nature of Ethereum has broadcast the transaction over the network and everyone can see the transaction and can replicate the transaction and the faster transaction win the token. The fix simply has to know the one who will receive tokens and specific the address on the transaction. But since we do not know the receiver address at the time we create the promo code it can be another problem. A solution is a REST web service to verify promo code and its signature then generate real redeem signature specific for a redeemer address. No database needed. The promo code and signature must be specific for the contract address too to prevent reuse promo code with the newer smart contract.

The Express router for the web service to verify and sign real redeem code.

PromoCode smart contract code.

The final workflow will like this:

  1. Fund owner run script to generate promo code and sign it then save the output to file for InDesign paper print. Approve token for PromoCode contract to transfer fund.
  2. The user receives a paper voucher and scan the QR code and open the link on Trust Wallet or MetaMask Dapp browser.
  3. When the user presses the “Redeem” button, the webpage calls the service to verify promo code with its signature and result back the real redeem signature for a specific redeemer only.
  4. The webpage call for “redeem” function with redeem signature to PromoCode smart contract.
  5. PromoCode smart contract verifies the code whether sign from a verifier or not and correct redeemer. If it passes verification transfer token to redeemer address.

End-user UX should be like scan QR code and click a button and confirm a transaction on DApp browser and it done token transfer to their wallet.

Future work:

  • Add amount, expire date to each promo code.
  • Separate the fund owner and verify wallet for better security.
  • Add REST web service to generate promo code to allow GUI admin.
  • Integrate redeem code with CarbonRadars App since it already got Ethereum wallet to gain more user.

Code
https://github.com/CarboneumProject/promocode/
https://github.com/CarboneumProject/contracts/tree/feature/promocode

Bonus
Real 88 Carboneum token promo code for the first reader:
https://carboneum.io/p/?c=MEDIUM_READER_001&s=0xed82a48ca405156c9d93ea35be64639c89ce1a0374cd89ea33c9fd69d656f0f51fe8a3fcc230cac594c02289a12021d9258e37639fc92dc67b974e4b93289a841c

--

--