# Getting Started

# Working examples

Working code can be worth a thousand words, so a good place to start is the GSN integration workshop (opens new window) which shows a barebones dapp before and after GSN integration.

Another resource is Capture The Flag (opens new window), which is the same "capture the flag" game, but as a React application.

# Adding GSN support to existing App

Adding GSN involves 4 steps

  1. Start GSN on your network
  2. Add GSN to your contract
  3. Select a paymaster and forwarder contract addresses
  4. Add GSN RelayProvider in your app

# Start GSN on your network.

GSN is already deployed to many testnets (and mainnets) - see the full list here. But for testing it locally, you need start it over your local ganache instance. To start GSN on local ganache, run the command:

npx gsn start

You can also run a process with both Hardhat node and GSN instance running in background by executing a command:

npx run-with-gsn 'ls'

# Add GSN to your contract

When receiving a native transaction, a contract accesses the msg.sender in order to recognize the caller. When receiving meta (relayed) transactions, the sender is different, so you must inherit a special base contract (ERC2771Recipient) and use a helper method called _msgSender() to get the address of the sender.

Note that your contract continues to work normally when called directly (without GSN) - in this case _msgSender() returns the real (msg.sender) sender unmodified.

You also need to have a forwarder, which is the contract you will receive the calls through.

import "@opengsn/contracts/src/ERC2771Recipient";

contract MyContract is ERC2771Recipient {
    constructor(address forwarder) {

    ... your contract code

# Select a paymaster and forwarder

The forwarder address is needed when deploying your contract. We have a forwarder deployed on each network. On your local ganache environment, the gsn start script described above saves locally the contract addresses, so you can deploy your contract as follows:

    // assuming this script is in "test" or "src" folder, 
    const forwarder = require( '../build/gsn/Forwarder').address
    myContract = MyContract.new(forwarder)

The Paymaster contract is the one which will actually pay for the transaction. For testing purposes, our gsn start deploys a paymaster that will accept and pay for all transactions.

    const paymaster = require('../build/gsn/Paymaster').address

We also deploy such a paymaster on all test networks For obvious reasons, there is no such "accept everything" paymaster on mainnets - any such deployed paymaster will soon get depleted by hackers.

# Use GSN RelayProvider in your app

Once your contract is set, you need to use a RelayProvider to access your contract. This is a wrapper to the regular web3 provider. All "view" operations are sent directly, but all transactions are relayed through GSN

const { RelayProvider } = require('@opengsn/provider')

const config = { 
    loggerConfiguration: {
        logLevel: 'debug'
const provider = await RelayProvider.newProvider({ provider: web3.currentProvider, config }).init()
const web3 = new Web3(provider);

With these changes, your application will route the requests through GSN.

To see that the sender address doesn't have to have eth, you can create a new one:

    from = provider.newAccount().address

or using web3:

    from = web3.eth.personal.newAccount('pwd')

See advanced section for all available configuration parameters.

Once you have connected your web3 instance to a RelayProvider, all transactions sent to contracts will be automatically routed through GSN:

const myRecipient = new web3.eth.Contract(abi, address);

// Sends the transaction via the GSN
await myRecipient.methods.myFunction().send({ from });

# Adding TypeScript types

If your project is using TypeScript, you may need to add the following lines to your tsconfig.json file:

  "include": [

# Running GSN on a local network

GSN is deployed on all major test and public networks. In order to test it locally with ganache, you need to deploy it locally.

See gsn start on how to start it locally, on your ganache instance.