I'm working on a dapp and am running into a dilemma regarding how to balance trustlessness with the cost of transactions for users.

In order to reduce gas usage by users, I want to be able to able to delegate certain transactions to the contract owner (i.e., the contract owner address sends transactions that include the user's address as a parameter as opposed to transactions coming directly from the user and using msg.sender), however, the big sticking point is in ensuring that a user is who he claims to be so that one user who simply knows the address of another user does not generate fake transactions.

Here's a simple idea that I have to try to accomplish this:

Authorization Process

1) User first accesses the site with MetaMask and requests to begin authorization. A request is sent to the contract owner's server that includes the user's public address.

2) The server generates a random string and records the string and user address in a database and sends the string back to user.

3) The user creates a password and, together with the string received from the server, creates a hash, which is then sent via a MetaMask transaction to the contract. The contract records the association between the user's address and the hash in a mapping.

4) If necessary, the server listens for an event to indicate that the user has created a new mapping entry to associate his address with the hash.

5) After the previous steps are completed, the user can initiate transactions by sending requests to the server, which included the user's password as well as the other instructions necessary to complete the transaction.

6) When the server receives the transaction request and password in step 5, it can create a hash of the password and the secret string assigned to the user and then compare that to the hash mapped to the user's address in the contract.

7) Any functions delegated to the contract owner would include a modifier to restrict access to the contract owner.

Key Points

  • The password (or a pure hash of the password, not including the random string) is stored neither in the contract nor the contract owner's database

  • It may not be necessary to combine the random string with the user's password before hashing, but this provides an additional layer of security

  • The user could change his password at any time by repeating steps 1-3

  • If a user alters the hash mapped to him outside of the above process, the server will not allow him to delegate transactions (his fault)

  • Impersonating the user in server requests would require 1) knowing the user's address and 2) knowing the user's password. This information could not be obtained by looking at previous transactions.

My knowledge of authorization patterns is still in the development stage, so apologies in advance if this has any glaring holes.


Given the problem that you describe, you may want to look at the Gas Station Network to see if this meets your needs: https://blog.openzeppelin.com/gsn-the-ultimate-ethereum-onboarding-solution/

For more information on the Gas Station Network please see the OpenZeppelin documentation: https://docs.openzeppelin.com/openzeppelin/gsn/what-is-the-gsn

If you have questions you can also ask in the Community Forum: https://forum.openzeppelin.com/

Disclosure: I am the Community Manager at OpenZeppelin

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.