# Fee Subsidies

## **Objective**

Fee subsidies enable users to interact with an app without paying gas fees themselves. Users do not need to hold any native tokens to execute transactions with the app’s contracts. Instead, gas costs are covered by a third party, typically the app’s developers.

## **Solution**

Fee subsidies can be built on ERC-4337 account abstraction. Rather than broadcasting transactions directly to the blockchain, users submit UserOperations to a bundler. The bundler aggregates these operations into a single transaction and sends it on-chain.

Within each UserOperation, the user specifies a paymaster contract. This paymaster (not the sender) pays the bundler for the gas used by the UserOperation.

The paymaster’s primary function is to determine whether a UserOperation qualifies for sponsorship, typically by checking if the operation interacts with the subsidized app. This verification is non-trivial, since users can deploy arbitrary smart account implementations. To prevent abuse, the paymaster must:

1. Inspect the UserOperation’s calldata to confirm it targets the sponsored contract(s).
2. Verify that the user’s account is running a pre-approved smart account implementation.

An example paymaster for sponsoring a single-contract app might look like this:

```solidity
contract MyPaymaster is IPaymaster {


   function validatePaymasterUserOp(
       PackedUserOperation calldata userOp,
       bytes32 userOpHash,
       uint256 maxCost
   ) external view override returns (bytes memory context, uint256 validationData) {
       if (msg.sender != address(entryPoint)) {
           revert InvalidEntryPoint();
       }
       // check if the sender use a whitelisted account implementation
       if (userOp.sender.codehash != keccak256(abi.encodePacked(bytes3(0xef0100), allowedSmartAccountImpl))) {
           revert InvalidAccountCodeHash();
       }


       // check if userOp.callData targets the whitelisted contract
       checkUserOpCallData(userOp.callData);


       // check if userOp.gasFees are within limits
       checkUserOpGasFees(userOp.gasFees);


       return ("", _packValidationData(false, 0, 0)); // accept paying gas
   }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.soniclabs.com/~/changes/292/technology/pectra-compatibility/fee-subsidies.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
