I have an ERC20 tokens contract with a function to mint tokens.

This function allows users to mint tokens after performing specific actions or activities on a website. If a user performs the action successfully, he will be able to send a transaction with the mint function and receive tokens.

My workflow and problems: In order to prevent users from interacting directly with the contract and mint as many tokens as they want, the contract only allows a certain eth address to call the mint function. That certain address will be set up on a server and sign the transactions if the actions were performed successfully. However, that means that this address will also have to pay for the gas.

Currently I am thinking about implementing another contract that will act as the only address that can call the mint function on the ERC20 contract. This new contract will receive a transaction from the user that incorporates variables, strings and nonce signed and hashed by the server address. The new contract will be able to decipher the data and know that the transaction really was approved by the server, and call the mint function from the tokens contract. That way users won’t be able to try and mint tokens directly or re-send transactions over and over to get more tokens.

A possible and simple implementation of this I've envisioned as follow:

  1. The server signs three pieces of information: the user's address, amount to be minted and an integer to be incremented with every transaction(aka mintRequestId) - this incrementation can be random.
  2. Those three hashed strings are passed to my user's client side logic and serve as arguments to my contract's method which is prompt to send:

myContract.methods.Mint( signedAddresses , signedMintAmount, signedMintRequestId ).send({from: userWallet})

  1. On my contract I ecrecover the three argument using my server's wallet public key and: A. compare msg.sender to signedAddresses. B. Get the amount. C. Make sure the mintRequestId is greater than the one saved in the contract. If all requirements are met the contract approves the minting and mintRequestId on contract changes.

Is this approach possible? too simple? where are the weak spots and how will you mend them? Any help and input on this matter would help!

Thank you.

  • Couldnt you just have a minting contract with a mapping limiting the number of tokens? But i guess if you want finite control of who can mint tokens, that makes sense – GrandFleet Dec 2 '18 at 16:26
  • That won't work with what I'm building. Need to allow users to mint whatever they deserve if they deserve it :) – Mike K Dec 2 '18 at 18:35
  • I think your approach should work if well implemented, you do not mention but you have to validate the server signature in the second contract. It should be possible to remove the second contract if you validate the server signature directly in the token contract. The client send address and amount to the server, server replies requestId and signature. Client send mint(amount, requestId, signature) to the token contract. Token ecverify(msg.sender, amount, request, signature) = serverAddress and acredits tokens to msg.sender. – Ismael Dec 5 '18 at 2:44
  • @Ismael Thanks, will try to check out ecverify instead of ecrecover. – Mike K Dec 6 '18 at 7:28
  • Sorry but I mean that ecverify() should be a utility function you have to implement that verifies its inputs agains the signature (internally it will call ecrecover). There's no ecverify function in solidity. – Ismael Dec 6 '18 at 15:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.