> For the complete documentation index, see [llms.txt](https://validium.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://validium.gitbook.io/docs/start-coding/quickstart/paymasters-introduction.md).

# Paymasters introduction

Learn about paymasters and use one to pay transaction fees with your own token

***

This tutorial makes use of smart contracts deployed in the previous two tutorials, [Deploy your first contract](/docs/start-coding/quickstart/deploy-your-first-contract.md) and [Create an ERC20 token](/docs/start-coding/quickstart/create-an-erc20-token.md). This section introduces one of the custom features of Validium: native account abstraction and paymasters.

In this tutorial we will:

* &#x20;Learn about paymasters.
* Review the testnet paymaster smart contract code.
* &#x20;Use the testnet paymaster to pay transaction fees with our own ERC20 token.

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

1. Before you start, make sure [that you’ve configured the Validium Sepolia Testnet in your browser wallet by following the instructions here](/docs/connect-to-validium.md).
2. In addition, fund your wallet with Validium Sepolia Testnet ETH using [one of the available faucets](https://docs.zksync.io/ecosystem/network-faucets).

### What is a Paymaster? <a href="#what-is-a-paymaster" id="what-is-a-paymaster"></a>

Paymasters in the Validium ecosystem represent a groundbreaking approach to handling transaction fees. They are special accounts designed to subsidize transaction costs for other accounts, potentially making certain transactions free for end-users. This feature is particularly useful for dApp developers looking to improve their platform's accessibility and user experience by covering transaction fees on behalf of their users.

Every paymaster has the following two functions:

* `validateAndPayForPaymasterTransaction` : this function uses the transaction parameters (fields like `from`, `amount` , `to` ) to execute the required validations and pay for the transaction fee.
* `postTransaction`: this optional function runs after the transaction is executed.

![Validium paymaster](https://docs.zksync.io/_ipx/q_90/images/101-paymasters/zksync-paymaster.png)

### Paymaster smart contract code <a href="#paymaster-smart-contract-code" id="paymaster-smart-contract-code"></a>

Although application developers are encouraged to create their own paymaster smart contract, Validium provides a testnet paymaster for convenience and testing purposes.

The paymaster smart contract code is provided "as-is" without any express or implied warranties.<br>

* Users are solely responsible for ensuring that their design, implementation, and use of the paymaster smart contract software complies with all applicable laws, including but not limited to money transmission, anti-money laundering (AML), and payment processing regulations.
* The developers and publishers of this software disclaim any liability for any legal issues that may arise from its use.

The testnet paymaster address is [0x3cb2b87d10ac01736a65688f3e0fb1b070b3eea3](https://sepolia.explorer.zksync.io/address/0x3cb2b87d10ac01736a65688f3e0fb1b070b3eea3)

TestnetPaymaster.sol

In the `validateAndPayForPaymasterTransaction` it is:

1. Checking that the paymasterInput is `approvalBased`.
2. Checking that the allowance of a given ERC20 is enough.
3. Transferring the transaction fee (`requiredETH`) in ERC20 from the user’s balance to the paymaster.
4. Transferring the transaction fee in ETH from the paymaster contract to the bootloader.

### How to send a transaction through a paymaster? <a href="#how-to-send-a-transaction-through-a-paymaster" id="how-to-send-a-transaction-through-a-paymaster"></a>

In order to send a transaction through a paymaster, the transaction must include the following additional parameters:

* `paymasterAddress`: the smart contract address of the paymaster
* `type`: should be `General` or `ApprovalBased` (to pay fees with ERC20 tokens)
* `minimalAllowance`: the amount of ERC20 tokens to be approved for spending (for `approvalBased` type paymasters only).
* `innerInput`: any payload we want to send to the paymaster (optional).

We’ll see an example next.

### Interacting with the testnet paymaster <a href="#interacting-with-the-testnet-paymaster" id="interacting-with-the-testnet-paymaster"></a>

We’re going to interact with the `ZeekMessages.sol` contract that we created in the first tutorial and use the ERC20 token that we deployed in the second tutorial to pay the transaction fees.

AtlasRemix

Click the following button to open the project in Atlas:

[Open script in Atlas](https://app.atlaszk.com/templates/33EAJkwrTKFaDJiEuy9Om?chainId=300\&openFile=/scripts/paymaster-transaction.ts)

It’ll open the script to send a transaction via the paymaster. Let’s go through the most important parts:

#### Retrieve the token balance <a href="#retrieve-the-token-balance" id="retrieve-the-token-balance"></a>

```javascript
// retrieve and print the current balance of the wallet
let ethBalance = await provider.getBalance(walletAddress)
let tokenBalance = await tokenContract.balanceOf(walletAddress)
console.log(`Account ${walletAddress} has ${ethers.formatEther(ethBalance)} ETH`);
console.log(`Account ${walletAddress} has ${ethers.formatUnits(tokenBalance, 18)} tokens`);
```

In this part we’re retrieving the ETH and ERC20 token balances of the account. We’ll compare them after the transaction is executed to see the difference.

#### Estimate transaction fee <a href="#estimate-transaction-fee" id="estimate-transaction-fee"></a>

```javascript
// retrieve the testnet paymaster address
const testnetPaymasterAddress = await zkProvider.getTestnetPaymasterAddress();

console.log(`Testnet paymaster address is ${testnetPaymasterAddress}`);

const gasPrice = await zkProvider.getGasPrice();

// define paymaster parameters for gas estimation
const paramsForFeeEstimation = utils.getPaymasterParams(testnetPaymasterAddress, {
  type: "ApprovalBased",
  token: TOKEN_CONTRACT_ADDRESS,
  // set minimalAllowance to 1 for estimation
  minimalAllowance: ethers.toBigInt(1),
  // empty bytes as testnet paymaster does not use innerInput
  innerInput: new Uint8Array(0),
});

// estimate gasLimit via paymaster
const gasLimit = await messagesContract.sendMessage.estimateGas(NEW_MESSAGE, {
  customData: {
    gasPerPubdata: utils.DEFAULT_GAS_PER_PUBDATA_LIMIT,
    paymasterParams: paramsForFeeEstimation,
  },
});

// fee calculated in ETH will be the same in
// ERC20 token using the testnet paymaster
const fee = gasPrice * gasLimit;
```

1. Retrieve the testnet paymaster address.
2. Generate the paymaster parameters to estimate the transaction fees passing the paymaster address, token address, and `ApprovalBased` as the paymaster flow type.
3. Retrieve the `gasLimit` of sending the transaction with the paymaster params.
4. Calculate the final estimated fee which is equal to `gasPrice` multiplied by `gasLimit`.

#### Send the transaction <a href="#send-the-transaction" id="send-the-transaction"></a>

```javascript
// new paymaster params with fee as minimalAllowance
  const paymasterParams = utils.getPaymasterParams(testnetPaymasterAddress, {
    type: "ApprovalBased",
    token: TOKEN_CONTRACT_ADDRESS,
    // provide estimated fee as allowance
    minimalAllowance: fee,
    // empty bytes as testnet paymaster does not use innerInput
    innerInput: new Uint8Array(0),
  });

  // full overrides object including maxFeePerGas and maxPriorityFeePerGas
  const txOverrides = {
    maxFeePerGas: gasPrice,
    maxPriorityFeePerGas: "1",
    gasLimit,
    customData: {
      gasPerPubdata: utils.DEFAULT_GAS_PER_PUBDATA_LIMIT,
      paymasterParams,
    }
  }

  console.log(`Sign the transaction in your wallet`);

  // send transaction with additional paymaster params as overrides
  const txHandle = await messagesContract.sendMessage(NEW_MESSAGE, txOverrides);
```

1. Create the new paymaster params with the calculated `fee` as `minimalAllowance` .
2. Complete the transaction overrides object with `maxFeePerGas`, `maxPriorityFeePerGas` and `gasPerPubdata`
3. Send the transaction including the `txOverrides`

#### Compare the final balance <a href="#compare-the-final-balance" id="compare-the-final-balance"></a>

```javascript
ethBalance = await provider.getBalance(walletAddress)
tokenBalance = await tokenContract.balanceOf(walletAddress)
console.log(`Account ${walletAddress} now has ${ethers.formatEther(ethBalance)} ETH`);
console.log(`Account ${walletAddress} now has ${ethers.formatUnits(tokenBalance, 18)} tokens`);
```

Finally we retrieve and print the ETH and ERC20 balances to see how they’ve changed.

### Run the script <a href="#run-the-script" id="run-the-script"></a>

To run the script, first enter the addresses of the `ZeekMessages.sol` and `TestToken.sol` contracts that we deployed previously ([Deploy your first contract](https://docs.zksync.io/build/start-coding/quick-start/deploy-your-first-contract) and [Erc20 Token](https://docs.zksync.io/build/start-coding/quick-start/erc20-token)) in the following variables at the beginning of the script:

```javascript
// Address of the ZeekMessages contract
const ZEEK_MESSAGES_CONTRACT_ADDRESS = "";
// Address of the ERC20 token contract
const TOKEN_CONTRACT_ADDRESS = ""
// Message to be sent to the contract
const NEW_MESSAGE = "This tx cost me no ETH!";
```

Next, make sure the script file is selected in the Atlas editor and click on the “Deploy” button.

![ERC20 interact script in Remix](https://docs.zksync.io/_ipx/q_90/images/101-paymasters/atlas-paymaster-script.png)

You’ll see the progress in the console.

If everything worked as expected, only the ERC20 balance will decrease, meaning the fee was paid with the ERC20 token instead of ETH.

### Takeaways <a href="#takeaways" id="takeaways"></a>

* Paymasters on Validium allow any account to pay fees with ERC20 tokens or enable gasless transactions.
* Paymasters are smart contracts that can have any validations and rules.
* To send a transaction through a paymaster, we only need to include additional parameters in the transaction.

### Next steps <a href="#next-steps" id="next-steps"></a>

* Learn more about paymasters and native account abstraction in [this section of the docs](https://docs.zksync.io/build/developer-reference/account-abstraction).
* Browse different paymaster examples in [this open source repository](https://github.com/matter-labs/paymaster-examples).
* Continue learning in ZKsync 101 by building a [GoFundMe clone](https://docs.zksync.io/build/start-coding/zksync-101).
