In the previous instalment of our blog series, titled "Paymasters with Trampoline - Part I: Token Paymasters", we delved into the fundamentals of paymasters and their role in automating gas fee payments. We also provided a comprehensive step-by-step guide on how to set up a token paymaster using Trampoline.
Continuing our exploration of paymasters, in this blog post, we will delve into the concept of verifying paymasters. For this purpose, we will utilize the verifying paymaster services offered by Stackup & Alchemy.
A verifying paymaster comes into play when an off-chain service assumes the responsibility of determining whether or not to pay the network fees for a transaction. Once the off-chain service has made this determination, it signs the userOp with a signature that the corresponding verifying paymaster contract can verify and accept on-chain.
There are several reasons why an off-chain service might opt for a sponsoring paymaster, including:
Establishing partnerships with web3 application and wallet developers who seek to simplify user onboarding for newcomers in the web3 space.
Providing incentives for platform-specific user behaviours.
Minting an NFT without incurring gas fees.
Deploying a wallet without expending gas, and numerous other use cases.
Verifying paymasters also empowers developers to sponsor gas based on off-chain activities such as interactions in Discord and other off-chain actions. Since these activities cannot be directly verified on-chain, creating a comprehensive on-chain paymaster becomes challenging. In such scenarios, developers can opt to create a verifying paymaster, wherein they can validate all relevant off-chain activities and, upon successful verification, sign the userOp with their verifying paymaster to sponsor the gas.
A verifying paymaster serves as an off-chain service that accepts signatures from entities authorized by the corresponding on-chain Verifying Paymaster contract.
Here's a breakdown of the underlying code:
During initialization, the paymaster incorporates a verifyingSigner, representing the authorized signer whose signatures will be accepted by the Verifying Paymaster. Stackup and Alchemy, among other service providers, configure this aspect using their private keys, allowing them to sign transactions on behalf of developers and offer paymaster services. The relevant code snippet highlighting this process can be observed below:
To ensure the security of the userOp and prevent replay attacks, it is essential to implement replay protection both within the same chain and across different chains. Without replay protection, if a signature is easily replayable, it would allow unauthorized individuals to drain the paymaster. To mitigate this risk, the contract incorporates a hash generation mechanism that requires the off-chain signing of both the userOp and chain ID information. Additionally, the contract includes a validUntil field, which can be utilized to defend against replay attacks if the provided timestamps have expired. Below is the code snippet illustrating the process of generating a hash for signing:
Once the hash is generated, the next step involves on-chain verification of the signature provided by the authorized signer's private key. It is crucial to note that the private key responsible for signing the hash cannot be stored on the client side due to security concerns. In the following example, we will demonstrate how to utilize services like Stackup or Alchemy, which offer API keys that enable them to sign the userOp on behalf of the user. To ensure the safety of these API keys, it is imperative to protect them diligently. Unauthorized access to these keys could result in unauthorized gas fee payments and lead to substantial financial liabilities. To help you maintain the security of your API keys, we have outlined a structure below, which can be implemented on a server-side environment.
In this blog post, we will explore the process of setting up a verifying paymaster using services such as Stackup and Alchemy. Instead of deploying our own paymaster contract, we will leverage these trusted services to handle the paymaster functionality.
To begin, let's outline the steps involved:
Create a server: To facilitate the interaction between our application and the paymaster services, we need to set up a server. This server will act as an intermediary to keep our API keys secret and make RPC requests to retrieve the paymaster and relevant data.
Implement an RPC call to the server: Within our extension, we need to incorporate an RPC call that connects to our server. This call will be responsible for fetching the paymaster and associated data from our servers. By making this request to our server, we ensure that sensitive information such as secret private API keys are securely stored and managed on the server side.
Server integration with paymaster services: On the server side, we utilize the secret private API key to make the necessary calls to the dedicated paymaster services, such as Stackup or Alchemy. These services will handle the logic of generating the paymaster and data field, ensuring the integrity and security of the process. The server then returns the retrieved paymaster and data to the client application to be signed and sent on-chain.
To view the code snippet that demonstrates the server setup, you can refer to the following link.
After creating the server using Express, you can run it directly from the root of your project using the command: npx nodemon server/index.ts
. This command will start the server and allow it to listen to incoming requests.
Within the server, a POST route /api/v1/paymaster/
has been created. This route will handle the requests from your extension to fetch the paymasterAndData
, which requires the parameters userOperation
and entryPoint
.
As we will be making an RPC call to our server from our extension, we have developed a custom RPC method called local_getPaymasterAndData
to facilitate this process. You can find the extension code snippet for this method below:
In the custom RPC method we created, we will include logic to forward the userOp
received in the request to the paymaster service URL obtained from either Stackup or Alchemy. This will allow us to fetch the paymaster and associated data. Here's an updated version of the code:
Given that both Stackup and Alchemy have different request parameters, we will examine each of them individually in the following sections. This approach allows us to ensure compatibility with the specific requirements of each service.
To set up Stackup's verifying paymaster, follow the steps below:
Generate an API key from Stackup:
Visit Stackup's website.
Create a new instance.
Navigate to the Paymaster section and copy the URL with the API key.
Once you have obtained the URL with the API key, refer to Stackup's documentation for the required RPC call. According to the documentation, you need to make an RPC call pm_sponsorUserOperation
with parameters such as userOp
, entryPoint
, and paymaster-specific data.
Paymaster-specific above can be of two types, depending on if you want to sponsor the gas completely or if you want the user to be able to pay gas via ERC20 tokens. As you may see in the code example below we are sending type =” payg”
, that means that this call will be sponsored using our Stackup account and a bill will be generated at the month's end that we will have to clear. We could have also used a config like:{ "type": "erc20token", "token": "USDC_ADDRESS" | "TEST_TOKEN_ADDRESS" }
The above config will allow users to pay gas via ERC20 tokens that you supply in the token address. Do note that currently Stackup only supports USDC on the mainnet and tokens on the testnet and no other ERC20 tokens are supported.
Here's an example of how to make the RPC call to Stackup's paymaster:
To set up Alchemy's paymaster, follow the steps below:
Generate an API key from Alchemy
Create a new APP (Here we are creating for Sepolia)
Go to Gas Manager
Create a new Policy
The new policy requires an app - select the app you created in step 1.b.
Follow the instructions and at the end you will get a Policy ID.
Once you have the Policy ID and App ID, you can make a call to Alchemy's endpoint alchemy_requestGasAndPaymasterAndData
to retrieve the paymaster and associated data. Refer to Alchemy's documentation for detailed information on this endpoint.
Here's an example of making an RPC call to obtain the paymaster data and other gas parameters using Alchemy's endpoint:
In the provided code, the PAYMASTER_SERVICE_URL
is set as https://{network}.g.alchemy.com/v2/{apiKey}
, where {network}
refers to the specific blockchain network being used (e.g., mainnet, rinkeby) and {apiKey}
represents the API key obtained from Alchemy for your App.
Additionally, the POLICY_ID
corresponds to the value obtained from step 1.f of the Alchemy setup process.
By utilizing the PAYMASTER_SERVICE_URL
and POLICY_ID
in the code, you can effectively connect to the Alchemy paymaster service and retrieve the necessary paymaster data, which can then be sent back to the client to be signed and sent to the blockchain.
Congratulations! You have now learned how to utilize the verifying paymaster services provided by Stackup and Alchemy. These services offer convenient and secure options for automating and managing gas fee payments, streamlining the development process for web3 applications.