Gas Subsidy

Gas Subsidy

⁠This feature requires an enterprise agreement

Contact Sales


The need for gas creates a barrier to onboarding users to web3. With Magic's Gas Subsidy offering, developers can offer a seamless, gasless experience on top of Magic's wallet and key management. Contact us for pricing information.


Gas subsidy SDK methods are available via the following client-side SDKs:


  1. Drive conversion: Focus on building innovative web3 experiences and Magic takes care of onboarding
  2. Single platform: Seamless technical implementation enabled by Magic wallet SDK integration
  3. Reduced complexity: No need to manage, monitor, and top up a crypto wallet

#Use Cases

Marketplaces: Create a secondary marketplace where users can buy and sell NFTs without needing crypto to pay for gas fees.

Games: Build web3 games with gasless onchain interactions, making it easy to target casual gamers and provide a more immersive experience.

DeFi: Help users tap into the power of decentralized financial applications without the added complexity of gas fees.


Currently we support Polygon and Tezos Etherlink for gasless transactions.

If you are interested in other EVM-based chains, please contact our Customer Success team using the help widget in the bottom-right corner of this page.

#Smart Contract Requirements

In order to utilize this feature, developers must implement ERC2771 standard into their smart contract. For more information, refer to the ERC2771 proposal.

Specifically, developers will need to leverage Magic's trusted forwarder contract; the addresses are the following:

  • 0xe4567ACcE23D69666B19f5C13b77c51488e41d0F - Amoy Testnet (ChainId: 80002)
  • 0xC077831B87CB5c335982f54b670eF8F0A04c71c6 - Polygon Mainnet (ChainId: 137)
  • 0xe4567ACcE23D69666B19f5C13b77c51488e41d0F - Etherlink Testnet (ChainId: 128123)

See below for a sample smart contract, which includes the Magic trusted forwader address. Note that instances of msg.sender should be replaced with _msgSender() for full ERC2771 compatibility.

01// Standard module for implementing Meta Transactions
02import "@openzeppelin/contracts/metatx/ERC2771Context.sol";
04contract YourNFTContract is ERC2771Context, ... {
06    // Hard-code Magic's Trusted Forwarder address
07    address private constant TRUSTED_FORWARDER = 0xB7B46474aAA2729e07EEC90596cdD9772b29Ecfb;
09    // Initialize the contract with Magic's Trusted Forwarder address
10    constructor() ERC2771Context(TRUSTED_FORWARDER) {...}
12    // Will be used instead of to support Meta Transactions
13    function _msgData() internal view override(Context, ERC2771Context) returns (bytes calldata) {
14        return ERC2771Context._msgData();
15    }
16    // Will be used instead of msg.sender to support Meta Transactions
17    function _msgSender() internal view override(Context, ERC2771Context) returns (address sender) {
18        return ERC2771Context._msgSender();
19    }

Once the contract is deployed, please reach out to Magic with your API key to add your contract address to our allowlist.


Smart contracts must be verified prior to use. For information on how to verify your smart contract, please see here.

#Client-side Integration

The following code demonstrates how a developer can integrate the the gasless transactions from the Magic SDK.

Ethers (v6)
Ethers (v5)
01const polygonNode = {
02  rpcUrl:'',
03  chainId: 80002, // Amoy testnet chain ID
05const magic = new Magic("ENTER_API_KEY_HERE", {network: polygonNode});
06const ethers = require('ethers')
08const provider = new ethers.BrowserProvider(magic.rpcProvider);
09const nftContractAddress ='ENTER_CONTRACT_ADDRESS_HERE'
11const nftContract = new ethers.Contract(
12      nftContractAddress,
13      ABI,
14      provider
17let transaction = await nftContract.transfer.populateTransaction(tokenId, destination)
19// Send gasless transaction to Magic Relayer
20const gasless_request = await magic.wallet.sendGaslessTransaction(
21    address, // User's Wallet address 
22    transaction,

Getting a response back from the SDK method call doesn't mean that the transaction is complete, but rather it means that the transaction has been received by our service. Depending on the chain, it should't take more than a few seconds to complete.

⁠If you have our Transaction Send and Sign UI toggled on under the Widget UI section, then our UI's will automatically wait until the transaction is complete for the user. If you would like to make your own UIs or just get back more details such as the transaction hash or the receipt of the transaction, then you will need to hit our get-request-state endpoint. You can do this by taking the request_id attribute you get back from the SDK call and calling the endpoint with a request_id parameter:

As a final note, before you are going live to a mainnet contract, please reach out to the Magic Customer Success team ([email protected]) as we will do one final enablement for the mainnet contract before going live.