Xai Network
English
English
  • About Xai
    • Welcome to Xai
    • Xai Introduction
      • Xai Blockchain
      • Xai Foundation
      • Xai Token
      • Blockchain Gaming
        • Current Limitations
        • The Future of Gaming
        • Gaming Evolved
      • Ex Populus Partnership
      • Offchain Labs Partnership
      • Vanguard League
      • FAQ
      • Important Links
      • Xai Brand Kit
    • Xai Protocol
      • Xai Basic Concepts
      • AnyTrust: Revolutionizing Blockchain Infrastructure
        • Reducing Costs through Trust Assumptions
        • Keysets for Flexibility
        • Data Availability Certificates (DACerts)
        • Dual Data Posting Mechanisms
        • Data Availability Servers (DAS)
        • Sequencer-Committee Interaction
      • Security considerations
    • Xai Governance Voting Guide
    • XAI Tokenomics
      • XAI Token’s Utility & Purpose
      • esXAI Token’s Utility & Purpose
      • The Redemption Process
      • Token metrics and initial allocation
      • XAI & esXAI Emissions & Burning
      • Network Rewards
      • Sentry Key Pricing Tiers
    • Sentry Keys Explained
      • How do Sentry Nodes Work
      • Who Can Operate A Sentry Node
      • Referee Smart Contract
        • Submission of Assertions
        • Claiming Rewards
        • Creating Assertion Hash and Checking Payout
      • Challenger Component
      • Key (NFT-based)
      • Sentry Download and Operation
      • Sentry Wallet Functionality
      • Licensing Impact
      • Sentry Node Hardware Requirements
      • Sentry Node Utility
      • Accruing Key Rewards
    • Sentry Key Purchase & Setup
      • Step 1: Purchase a Sentry Key
        • Option 1: Buy Sentry Key via the website
        • Option 2: Buy Sentry Key via Xai Sentry Node desktop app
        • Option 3: Buy Sentry Key via Xai Sentry Node CLI (command line interface)
          • How to view the price of a Key via the CLI
        • Option 4: Buy Sentry Key via Node License Contract on Arbiscan
      • Step 2: Download & Run the Xai Sentry Node
      • Step 3: Complete Requirements to Accrue esXAI
        • Step 3a: Set Up & Fund the Sentry Wallet
          • How to Obtain Arbitrum ETH
          • How to import your wallet as the Sentry Wallet in the desktop app
        • Step 3b: Start the Sentry Wallet (a.k.a Operator)
          • How to create a wallet using the CLI
        • Step 3c: Assign Keys to the Sentry Wallet
      • Step 4: Complete KYC (or KYB) to Claim XAI redemptions
        • How to interpret a Pending KYC status
      • Common Troubleshooting Steps
        • How do I run a Xai Node on VPS?
          • Step 1: Choose a VPS
          • Step 2: Log in to a server
          • Step 3: Set up Xai Sentry Node
          • Step 4: Set up a Screen
          • Step 5: Start Xai Sentry Node
          • Step 6: Monitor your Node via Screen
          • Step 7: Updating your node
        • How do I prevent others from using my Sentry Wallet or Operator?
        • Why don't I see the KYC link on the desktop app?
        • How do I know my Node is running in the CLI?
        • How do I KYC if I'm using the CLI?
        • How can I see my rewards?
        • Crashing, inconsistent Emissions / missing revert data errors
        • According to BlockPass, my KYC is approved, but the desktop app still says I am not approved
        • I see "Transaction in progress" message after assigning my wallet. Did my wallet not get assigned?
        • How do I delegate my Keys to another user's operator?
        • Why did my Accrued esXAI balance decrease?
        • What are the legitimate contracts owned & operated by Xai Foundation?
        • Why do I get an error for challenge 2012?
      • How To Videos
        • Desktop Client
          • Download & Install Xai Node Desktop Client
          • Import & Start Your Sentry Wallet
          • Assign Wallets Containing Keys to the Sentry Wallet
          • Fund Sentry Wallet with Arbitrum One ETH
          • Submit KYC
          • Claim Node Rewards after Passing KYC
        • Command Line Interface (CLI)
          • Download & Install Xai Node CLI
          • Boot Operator & Interpret Status Logs
          • Add Custom Operator
          • Track Accrued esXAI
          • KYC When Using CLI
      • Redeem Referral Rewards
    • Open Initiatives
      • Completed Initiatives
      • Xai & Sentry Nodes Initiatives
      • Xai Protocol Initiatives
  • Staking Explained
    • Staking v1 and v2
    • Staking Pool Guide
      • Create a Pool
      • Stake esXAI
      • Stake Sentry Keys
      • Generating Rewards
      • Unstaking
    • Staking Rewards & Tiers
    • Time Cooldown
    • Gas Optimizations
  • Tiny Sentry Key FAQ
    • FAQ (Indonesian / Bahasa Indonesia)
    • FAQ (Korean / 한국어)
    • FAQ (Hindi / हिन्दी) - कुंजी विभाजन सामान्य प्रश्न
    • FAQ (Chinese / 中文)
  • Key Sale Referrals
  • Key Split Update (technical)
  • Build on Xai
    • Xai Chains & Parameters
      • Connect to Xai Mainnet
      • Bridge to Xai Mainnet
      • Connect to Xai Testnet (Sepolia)
      • Bridge to Xai Testnet
      • Bridged Token Addresses
      • Contract Addresses
    • How to run a full node for Xai chain
    • How to get $XAI
      • Centralized Exchanges
      • Decentralized Exchanges
        • Camelot
    • Developer Tools
      • Block Explorers
      • RPC
        • Ankr
        • Nirvana
        • QuickNode
      • Token Bridges
        • Xai native bridge
        • Gas.zip
        • Relay
      • Wallets
      • Marketplace
        • Reservoir
        • Snag Solutions
        • RaribleX
      • On chain randomisation
        • Supra VRF
  • Xai Gaming Dev Resources
    • Xai Connect
      • Overview
      • Integrate with Xai Connect
    • Build with thirdweb
      • Overview
      • Connect
      • Contracts
      • Wallets
      • Account Abstraction
      • SDKs
      • Engine
      • Web3 APIs
    • Build with Sequence
    • Subgraph
    • Xai Gas Subsidy
  • Xai Vanguard: Genesis
    • Getting Started
      • Leaderboard
      • Discord
    • Chapter 01: Onboarding
    • Chapter 02: Minting
      • Minting from Contract
    • Chapter 03: Discord
      • Obtaining esXAI
      • Obtaining XAI
      • Buy Sentry Key
    • Chapter 04: Xai Staking Pools
    • Chapter 05: Unicorn Bingo
    • Chapter 06: Bridging
    • Chapter 08: Build on Xai
      • Thirdweb: Creator Portal Walkthrough
      • Sequence: Xai Builder Walkthrough
    • Chapter 09: Camelot
    • Chapter 10: Crypto Unicorns
    • Chapter 11: Tarochi
    • Chapter 12 - My Angry Yakuza Girlfriend
    • Chapter 13 - Rainbow Rumble
    • Chapter 14 - The Lost Glitches
  • Xai Vanguard: Previous Seasons
    • XAI Token Claim
      • Claim Details
  • Play Games on Xai
    • Connect your wallet to Xai
    • Xai Games Catalog
    • Final Form
      • Card Sets
      • Card System
      • Where to Get Cards
      • ❔FAQ
Powered by GitBook
On this page
  • XAI Gas Subsidy
  • How the XAI Gas Subsidy works
  • Requirements
  • How to forward the meta-transaction to the XAI Relayer API
  • Get a Xai Subsidy ProjectID
  1. Xai Gaming Dev Resources

Xai Gas Subsidy

PreviousSubgraphNextGetting Started

Last updated 9 months ago

XAI Gas Subsidy

The XAI Gas Subsidy uses the ERC-2771 standard for secure protocol for native meta transactions. With the XAI Gas Subsidy XAI can sponsor your user's transactions so they don't have to own native XAI.

How the XAI Gas Subsidy works

Instead of using a contract write function, the user will sign a typed data message () with the message implementing the meta-transaction. This means when you use the XAI Gas Subsidy your user does not call the contract directly, instead the XAI relayer will forward to your smart contract.

Relayer Endpoints:

Xai Mainnet Relayer: https://relayer.xai.games/ Xai Mainnet API Docs: https://docs.xai.games/gas-relayer/#/relayer

Xai Testnet Relayer: https://develop.relayer.xai.games/ Xai Testnet API Docs: https://develop.docs.xai.games/gas-relayer/#/relayer

Requirements

To use the XAI Gas Subsidy your contracts need to follow the _msgSender() overwrite and make sure to only use the _msgSender() when updating a user's state. The requires the validation for a trusted forwarder contract when interacting on behalf of a user. The trusted forwarder contract for your ecosystem's contracts should be owned by you. The trusted forwarder contract will be able to execute transactions on behalf of your user's wallet. Interacting with ERC-20 tokens while using the Xai subsidy requires implementing the ERC-2771 standard. Gasless approvals can be achieved by implementing the ERC-2612 Permit Extension. Any ERC-20 contracts that don't either implement ERC-2771 or ERC-2612 can not be used for sponsored transaction. FOR ALL INTERACTIONS ALLOWING THE FORWARDER, DO NOT USE msg.sender IN YOUR CONTRACTS, YOU MUST USE _msgSender() or your contract's state will not be updated properly For testing purposes there is a Xai mainnet and testnet forwarder deployed:

  • Xai mainnet Forwarder: 0x4AfA378FDDc9829B1D40655ED5EDBCC31404dee6

  • Xai testnet Forwarder: 0x31635b37347258d7c6f83bDC664c5516Da8e6fD7

The _msgSender() overrides the default msg.sender. As the default msg.sender would be the address of the forward contract instead of the user wallet address:

function _msgSender() internal view returns (address) {
    uint256 calldataLength = msg.data.length;
    if (isTrustedForwarder(msg.sender) && calldataLength >= 20) {
        return address(bytes20(msg.data[calldataLength - 20:]));
    } else {
        return super._msgSender();
    }
}

The _msgDate() overrides the default msg.data:

function _msgData() internal view returns (bytes calldata) {
    uint256 calldataLength = msg.data.length;
    if (isTrustedForwarder(msg.sender) && calldataLength >= 20) {
        return msg.data[:calldataLength - 20];
    } else {
        return super._msgData();
    }
}

The trusted forwarder check is important to only allow a trusted forwarder contract to call the functions on user's behalf:

function isTrustedForwarder( address forwarder ) public view returns (bool) {
    return forwarder == trustedForwarder;
}

How to sign meta transactions

The user needs to signs a message based on the EIP-712 sign typed message using the 2771 forward request standard:

export function createTypedData(wallet: `0x${string}`, receiver: `0x${string}`, forwarderAddress: `0x${string}`, nonce: number) {

    //Create the data from your smart contract instance
    const data = receiverContract.methods.mint(wallet, BigInt(amount)).encodeABI();
    
    const domain = {
        name: "Forwarder",                      // Forwarder typed name (https://eips.ethereum.org/EIPS/eip-2771)
        version: '1',                           // Forwarder typed version (https://eips.ethereum.org/EIPS/eip-2771)
        chainId: BigInt(660279),                // XAI mainnet
        verifyingContract: forwarderAddress,    //Forwarder address
    } as const;
    const message = {
        from: wallet,                           // The user wallet (the wallet that should be msgSender in your contract)
        to: receiver,                           // The address of the contract to call the write function from
        value: BigInt(0),                       // Value has to be 0, the XAI Relayer can only sponsor transaction fees
        gas: BigInt(DEFAULT_GAS),               // The expected transaction gas costs 
        nonce: BigInt(nonce),                   // The nonce for the user on the forwarder contract (https://eips.ethereum.org/EIPS/eip-2771)
        data,                                   // The encoded function identifier to define the contract function to 
    } as const;

    const typedData = {
        types: {
            EIP712Domain: [
                { name: "name", type: "string" },
                { name: "version", type: "string" },
                { name: "chainId", type: "uint256" },
                { name: "verifyingContract", type: "address" },
            ],
            ForwardRequest: [
                { name: "from", type: "address" },
                { name: "to", type: "address" },
                { name: "value", type: "uint256" },
                { name: "gas", type: "uint256" },
                { name: "nonce", type: "uint256" },
                { name: "data", type: "bytes" },
            ],
        },
        primaryType: "ForwardRequest",
        domain,
        message
    } as const;

    return typedData;
}

The nonce must be the latest nonce from the forwarder for the specific user:

export const getNonce = async (userWallet: string, forwarderAddress: string): Promise<number> => {
	const forwarderContract = new web3.eth.Contract(ForwarderABI, forwarderAddress);
	const nonce = await forwarderContract.methods.nonces(userWallet).call();
	return Number(nonce);
}

Now to sign this typedData we use the EIP-712 standard to get the signature. We use the signTypedData() from wagmi/core:

const signature = await signTypedData(config, typedData);

How to forward the meta-transaction to the XAI Relayer API

Use the signed request signature and the raw request body to forward the transaction and get the transaction fee sponsored by the XAI Gas Subsidy:

type ForwardRequest = {
    from: string;
    to: string;
    value: string;
    gas: string;
    nonce: string;
    data: string;
    signature: string;
    forwarderAddress: string;
};

const forwardTransaction = async (
    {
        typedData, // Typed data from createTypedData()
        signature, // user signature from signTypedData()
        forwarderAddress // The forwarder address used
    }:
    {
        typedData: TypedData,
        signature: string,
        forwarderAddress: string
    }
) => {

    //Create the request body from the meta-transaction object the user signed
    const requestBody: ForwardRequest = {
        from: typedData.message.from,
        to: typedData.message.to,
        value: "0",
        gas: typedData.message.gas,
        nonce: typedData.message.nonce,
        data: typedData.message.data,
        signature,
        forwarderAddress
    }

    try {
        const res = await fetch(`https://relayer.xai.games/forward/[YOUR_PROJECT_ID]`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(requestBody),
        });

        const data = await res.json();
        if (!res.ok) {
            throw new Error(data.message);
        }
        console.log("Transaction complete: ", data.txHash)

    } catch (error) {
        console.error('Error fetching data:', error);
        alert("Error sending to relayer\n" + error);
    }
}

The request will return the transaction hash as a success response or an error string if the transaction would fail or the user has not enough balance left for their sponsoring with your project.

You can request the users current balance from a GET request to the XAI Relayer API https://relayer.xai.games/quota/[YOUR_PROJECT_ID]/[USER_WALLET] This will return the user's quota Object:

{
    balanceWei: string;             // The remaining amount for a user that you pay for his transaction gas
    nextRefillTimestamp: number;    // The next moment the balance gets refilled
    nextRefillAmountWei: string;    // The amount of wei that gets refilled on the next refill
    lastRefillTimestamp: number;    // The last time the balance for a user got refilled
}

Get a Xai Subsidy ProjectID

Contact us on our Discord or Telegram channels to get your ProjectID.

EIP-712
ERC-2771
ERC-2771
ERC-2771
https://explorer.xai-chain.net/address/0x4AfA378FDDc9829B1D40655ED5EDBCC31404dee6/contracts#address-tabs
https://testnet-explorer-v2.xai-chain.net/address/0x31635b37347258d7c6f83bDC664c5516Da8e6fD7/read-proxy#address-tabs