fairDataSociety / fdp-contracts

Fair Data Protocol smart contracts and its utilities
4 stars 1 forks source link

Upgrade FDP Contracts for Gasless Transactions with OpenGSN 3 #146

Closed IgorShadurin closed 7 months ago

IgorShadurin commented 1 year ago

We can upgrade our FDP contracts to use OpenGSN 3. This will enable us to offer gasless transactions, enhancing user experience and facilitating onboarding. For developers, the changes required in the contracts are fairly minimal.

What is this?

This task involves integrating OpenGSN 3 (link: https://github.com/opengsn/gsn) with our FDP contracts. The OpenGSN network allows us to implement gasless transactions, providing a smoother experience for our users.

How does it work?

Once the contracts are upgraded and a trusted forwarder is established, the system can accept signed data from a user and carry out actions on their behalf. The concept of a "trusted forwarder" is pivotal here.

Trusted forwarders act as intermediaries between the user and the contract. They receive signed messages from the user, validate them, and then execute the transaction in the contract on the user's behalf. You can use existing trusted forwarders or deploy your own. The key is to trust the forwarder to validate user's signatures correctly.

Our relayer contract, which we can fund with ETH, pays the gas cost. This results in a gas-free experience for users. From a user's perspective, they simply sign a message indicating what action they want the contract to take and send it off. The forwarder and relayer handle the rest.

If the relayer runs out of funds or if a user wants to control the transactions using their own resources, they can easily switch back to the traditional transaction method. In this scenario, they would need to sign and submit their transactions as they normally would when interacting with Ethereum contracts. The functionality of the contract remains the same, and the gasless feature is an optional add-on rather than a requirement.

This system can be used with newly created wallets as well as existing ones like MetaMask. For instance, when a user wants to interact with the contract using MetaMask, a window will pop up prompting the user to sign a message. The user doesn't have to worry about gas fees or having ETH in their wallet. They just need to review and approve the message. The rest of the transaction is handled behind the scenes, providing a seamless and user-friendly experience.

What needs to be done?

For each contract, you'll need to:

  1. Import the ERC2771Recipient contract
  2. Extend current contracts with ERC2771Recipient
  3. Replace all instances of msg.sender with msgSender()
  4. Add functionality to change the trusted forwarder

Current vs Suggested approach

Currently, a user has to create a wallet through our site and get a certain amount of Sepolia or other tokens from a faucet. Some faucets require additional registration, some lack test tokens, and others may get stuck during the process. This can be a barrier to user onboarding and can cause significant delays compared to traditional registration processes.

By upgrading our contracts, we can store a specific amount of test tokens for users to use exclusively for the registration process. This eliminates the need for users to understand how faucets work, wait for tokens to arrive, etc. As soon as a user visits our site and creates a wallet, they can immediately send transactions for registration via our relayer, simplifying the process significantly.

The relayer, in this context, is a wallet with funds and custom logic that can be hosted on our server or services such as OpenZeppelin Defender (link: https://defender.openzeppelin.com/). It accepts signed requests from the user's wallet, sends them to the forwarder contract, which securely executes the user's command in the FDS contract on the user's behalf. The relayer logic is a JS lambda function that can be run on our side (AWS, custom server) or on Defender's side.

Pros of suggested approach

Cons of suggested approach

Installation and usage of OpenGSN in an npm project

Here are the steps to install OpenGSN contracts in an npm project:

  1. Install OpenGSN using npm. Run npm install @opengsn/gsn
  2. Import the required contracts in your contract file. Example: import "@opengsn/gsn/contracts/BaseRelayRecipient.sol";
  3. Extend your contract with the imported contract.
  4. Replace msg.sender with _msgSender() function provided by OpenGSN.
  5. Write the logic to update the trusted forwarder.