---
title: "गैस शुल्क प्रायोजित करना: अपने उपयोगकर्ताओं के लिए लेन-देन की लागत को कैसे कवर करें"
description: "निजी कुंजी और पता बनाना आसान है; यह केवल सही सॉफ़्टवेयर चलाने की बात है। लेकिन दुनिया में कई ऐसी जगहें हैं जहां लेन-देन भेजने के लिए ETH प्राप्त करना बहुत कठिन है। इस ट्यूटोरियल में आप सीखेंगे कि अपने स्मार्ट अनुबंध में उपयोगकर्ता द्वारा हस्ताक्षरित, ऑफचेन संरचित डेटा को निष्पादित करने के लिए ऑनचेन गैस लागत को कैसे कवर किया जाए। आप उपयोगकर्ता से लेन-देन की जानकारी वाले एक स्ट्रक्चर पर हस्ताक्षर करवाते हैं, जिसे आपका ऑफचेन कोड फिर एक लेन-देन के रूप में ब्लॉकचेन पर सबमिट करता है।"
author: "ओरी पोमेरेंट्ज़"
tags: ["गैसलेस", "Solidity", "eip-712", "मेटा-लेन-देन"]
skill: intermediate
breadcrumb: "गैस प्रायोजन"
lang: hi
published: 2026-02-27
---

## परिचय {#introduction}

यदि हम चाहते हैं कि इथेरियम [एक अरब और लोगों](https://blog.ethereum.org/category/next-billion) की सेवा करे, तो हमें बाधाओं को दूर करने और इसे उपयोग करने में यथासंभव आसान बनाने की आवश्यकता है। इस बाधा का एक स्रोत गैस शुल्क का भुगतान करने के लिए ETH की आवश्यकता है।

यदि आपके पास एक विकेंद्रीकृत एप्लिकेशन (dapp) है जो उपयोगकर्ताओं से पैसा कमाता है, तो उपयोगकर्ताओं को आपके सर्वर के माध्यम से लेन-देन सबमिट करने देना और लेन-देन शुल्क का भुगतान स्वयं करना समझदारी हो सकती है। क्योंकि उपयोगकर्ता अभी भी अपने वॉलेट में एक [EIP-712 प्राधिकरण संदेश](https://eips.ethereum.org/EIPS/eip-712) पर हस्ताक्षर करते हैं, वे इथेरियम की अखंडता की गारंटी बनाए रखते हैं। उपलब्धता उस सर्वर पर निर्भर करती है जो लेन-देन को रिले करता है, इसलिए यह अधिक सीमित है। हालाँकि, आप चीजों को इस तरह सेट कर सकते हैं कि उपयोगकर्ता सीधे स्मार्ट अनुबंध तक भी पहुँच सकें (यदि उन्हें ETH मिलता है), और यदि अन्य लोग लेन-देन को प्रायोजित करना चाहते हैं तो उन्हें अपने स्वयं के सर्वर स्थापित करने दें।

इस ट्यूटोरियल की तकनीक केवल तभी काम करती है जब आप स्मार्ट अनुबंध को नियंत्रित करते हैं। अन्य तकनीकें भी हैं, जिनमें [खाता अमूर्तन](https://eips.ethereum.org/EIPS/eip-4337) शामिल है जो आपको अन्य स्मार्ट अनुबंधों के लिए लेन-देन प्रायोजित करने देती हैं, जिन्हें मैं भविष्य के ट्यूटोरियल में कवर करने की उम्मीद करता हूँ।

नोट: यह उत्पादन-स्तर (production-level) का कोड _नहीं_ है। यह महत्वपूर्ण हमलों के प्रति संवेदनशील है और इसमें प्रमुख विशेषताओं का अभाव है। इस गाइड के [भेद्यता (vulnerabilities) अनुभाग](#vulnerabilities) में और जानें।

### पूर्वापेक्षाएँ {#prerequisites}

इस ट्यूटोरियल को समझने के लिए आपको पहले से ही निम्नलिखित से परिचित होना चाहिए:

- Solidity
- JavaScript
- React और WAGMI। यदि आप इन यूजर इंटरफेस टूल्स से परिचित नहीं हैं, तो [हमारे पास उसके लिए एक ट्यूटोरियल है](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/)।

## नमूना एप्लिकेशन {#sample-app}

यहाँ नमूना एप्लिकेशन Hardhat के `Greeter` अनुबंध का एक प्रकार है। आप इसे [GitHub पर](https://github.com/qbzzt/260301-gasless) देख सकते हैं। स्मार्ट अनुबंध पहले से ही [Sepolia](https://sepolia.dev/) पर, [`0xC87506C66c7896366b9E988FE0aA5B6dDE77CFfA`](https://eth-sepolia.blockscout.com/address/0xC87506C66c7896366b9E988FE0aA5B6dDE77CFfA) पते पर डिप्लॉय किया गया है।

इसे काम करते हुए देखने के लिए, इन चरणों का पालन करें।

1. रिपॉजिटरी को क्लोन करें और आवश्यक सॉफ़्टवेयर इंस्टॉल करें।

   ```sh
   git clone https://github.com/qbzzt/260301-gasless.git
   cd 260301-gasless/server
   npm install
   ```

2. `PRIVATE_KEY` को ऐसे वॉलेट पर सेट करने के लिए `.env` को संपादित करें जिसमें Sepolia पर ETH हो। यदि आपको Sepolia ETH की आवश्यकता है, तो [फॉसेट का उपयोग करें](/developers/docs/networks/#sepolia)। आदर्श रूप से, यह निजी कुंजी आपके ब्राउज़र वॉलेट में मौजूद कुंजी से अलग होनी चाहिए।

3. सर्वर प्रारंभ करें।

   ```sh
   npm run dev
   ```

4. URL [`http://localhost:5173`](http://localhost:5173) पर एप्लिकेशन ब्राउज़ करें।

5. वॉलेट से कनेक्ट करने के लिए **Connect with Injected** पर क्लिक करें। वॉलेट में स्वीकृति दें, और यदि आवश्यक हो तो Sepolia में बदलाव को स्वीकृति दें।

6. एक नया अभिवादन (greeting) लिखें और **Update greeting via sponsor** पर क्लिक करें।

7. संदेश पर हस्ताक्षर करें।

8. लगभग 12 सेकंड (Sepolia पर ब्लॉक समय) प्रतीक्षा करें। प्रतीक्षा करते समय आप लेन-देन देखने के लिए सर्वर के कंसोल में URL देख सकते हैं।

9. देखें कि अभिवादन बदल गया है, और अंतिम अपडेट किए गए पते का मान अब आपके ब्राउज़र वॉलेट का पता है।

यह कैसे काम करता है, यह समझने के लिए, हमें यह देखना होगा कि यूजर इंटरफेस में संदेश कैसे बनाया जाता है, इसे सर्वर द्वारा कैसे रिले किया जाता है, और स्मार्ट अनुबंध इसे कैसे प्रोसेस करता है।

### यूजर इंटरफेस {#ui-changes}

यूजर इंटरफेस [WAGMI](https://wagmi.sh/) पर आधारित है; आप इसके बारे में [इस ट्यूटोरियल में](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/) पढ़ सकते हैं।

यहाँ बताया गया है कि हम संदेश पर हस्ताक्षर कैसे करते हैं:

```js
const signGreeting = useCallback(
```

React हुक [`useCallback`](https://react.dev/reference/react/useCallback) हमें घटक (component) के फिर से ड्रा होने पर उसी फ़ंक्शन का पुन: उपयोग करके प्रदर्शन में सुधार करने देता है।

```js
    async (greeting) => {
        if (!account) throw new Error("Wallet not connected")
```

यदि कोई खाता नहीं है, तो एक त्रुटि (error) उत्पन्न करें। ऐसा कभी नहीं होना चाहिए क्योंकि UI बटन जो उस प्रक्रिया को शुरू करता है जो `signGreeting` को कॉल करती है, उस स्थिति में अक्षम (disabled) होता है। हालाँकि, भविष्य के प्रोग्रामर उस सुरक्षा उपाय को हटा सकते हैं, इसलिए इस स्थिति की यहाँ भी जाँच करना एक अच्छा विचार है।

```js
        const domain = {
            name: "Greeter",
            version: "1",
            chainId,
            verifyingContract: contractAddr,
        }
```

[डोमेन सेपरेटर](https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator) के लिए पैरामीटर। यह मान स्थिर (constant) है, इसलिए बेहतर-अनुकूलित कार्यान्वयन में, हम इसे हर बार फ़ंक्शन कॉल किए जाने पर पुनर्गणना करने के बजाय एक बार गणना कर सकते हैं।

- `name` एक उपयोगकर्ता-पठनीय नाम है, जैसे कि उस dapp का नाम जिसके लिए हम हस्ताक्षर तैयार कर रहे हैं।
- `version` संस्करण (version) है। विभिन्न संस्करण संगत (compatible) नहीं हैं।
- `chainId` वह चेन है जिसका हम उपयोग कर रहे हैं, जैसा कि [WAGMI द्वारा](https://wagmi.sh/react/api/hooks/useChainId) प्रदान किया गया है।
- `verifyingContract` वह अनुबंध पता है जो इस हस्ताक्षर को सत्यापित करेगा। हम नहीं चाहते कि एक ही हस्ताक्षर कई अनुबंधों पर लागू हो, यदि कई `Greeter` अनुबंध हैं और हम चाहते हैं कि उनके अलग-अलग अभिवादन हों।

```js

        const types = {
            GreetingRequest: [
                { name: "greeting", type: "string" },
            ],
        }
```

डेटा प्रकार जिस पर हम हस्ताक्षर करते हैं। यहाँ, हमारे पास एक ही पैरामीटर है, `greeting`, लेकिन वास्तविक जीवन के सिस्टम में आमतौर पर अधिक होते हैं।

```js
        const message = { greeting }
```

वास्तविक संदेश जिस पर हम हस्ताक्षर करना और भेजना चाहते हैं। `greeting` फ़ील्ड का नाम और इसे भरने वाले चर (variable) का नाम दोनों है।

```js
        const signature = await signTypedDataAsync({
            domain,
            types,
            primaryType: "GreetingRequest",
            message,
        })
```

वास्तव में हस्ताक्षर प्राप्त करें। यह फ़ंक्शन एसिंक्रोनस है क्योंकि उपयोगकर्ताओं को डेटा पर हस्ताक्षर करने में (कंप्यूटर के दृष्टिकोण से) लंबा समय लगता है।

```js
        const r = `0x${signature.slice(2, 66)}`
        const s = `0x${signature.slice(66, 130)}`
        const v = parseInt(signature.slice(130, 132), 16)

        return {
            req: { greeting },
            v,
            r,
            s,
        }
    },
```

फ़ंक्शन एक एकल हेक्साडेसिमल मान लौटाता है। यहाँ हम इसे फ़ील्ड्स में विभाजित करते हैं।

```js
    [account, chainId, contractAddr, signTypedDataAsync],
)
```

यदि इनमें से कोई भी चर बदलता है, तो फ़ंक्शन का एक नया उदाहरण (instance) बनाएँ। `account` और `chainId` पैरामीटर उपयोगकर्ता द्वारा वॉलेट में बदले जा सकते हैं। `contractAddr` चेन Id का एक फ़ंक्शन है। `signTypedDataAsync` नहीं बदलना चाहिए, लेकिन हम इसे [एक हुक](https://wagmi.sh/react/api/hooks/useSignTypedData) से आयात करते हैं, इसलिए हम निश्चित नहीं हो सकते, और इसे यहाँ जोड़ना सबसे अच्छा है।

अब जब नए अभिवादन पर हस्ताक्षर हो गए हैं, तो हमें इसे सर्वर पर भेजना होगा।

```js
  const sponsoredGreeting = async () => {
    try {
```

यह फ़ंक्शन एक हस्ताक्षर लेता है और इसे सर्वर पर भेजता है।

```js
      const signedMessage = await signGreeting(newGreeting)
      const response = await fetch("/server/sponsor", {
```

हम जिस सर्वर से आए हैं, उसमें `/server/sponsor` पथ (path) पर भेजें।

```js
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(signedMessage),
      })
```

जानकारी को JSON-एन्कोडेड भेजने के लिए `POST` का उपयोग करें।

```js
      const data = await response.json()
      console.log("Server response:", data)
    } catch (err) {
      console.error("Error:", err)
    }
  }
```

प्रतिक्रिया (response) आउटपुट करें। उत्पादन सिस्टम पर हम उपयोगकर्ता को प्रतिक्रिया भी दिखाएंगे।

### सर्वर {#server}

मुझे अपने फ्रंट-एंड के रूप में [Vite](https://vite.dev/) का उपयोग करना पसंद है। यह स्वचालित रूप से React लाइब्रेरीज़ को सर्व करता है और फ्रंट-एंड कोड बदलने पर ब्राउज़र को अपडेट करता है। हालाँकि, Vite में बैकएंड टूलिंग शामिल नहीं है।

समाधान [`index.js`](https://github.com/qbzzt/260301-gasless/blob/main/server/index.js) में है।

```js
  app.post("/server/sponsor", async (req, res) => {
    ...
  })

  // बाकी सब कुछ Vite को संभालने दें
  const vite = await createViteServer({
    server: { middlewareMode: true }
  })

  app.use(vite.middlewares)
```

पहले हम उन अनुरोधों के लिए एक हैंडलर पंजीकृत करते हैं जिन्हें हम स्वयं संभालते हैं (`/server/sponsor` पर `POST`)। फिर हम अन्य सभी URL को संभालने के लिए एक Vite सर्वर बनाते हैं और उसका उपयोग करते हैं।

```js
  app.post("/server/sponsor", async (req, res) => {
    try {
      const signed = req.body

      const txHash = await sepoliaClient.writeContract({
        address: greeterAddr,
        abi: greeterABI,
        functionName: 'sponsoredSetGreeting',
        args: [signed.req, signed.v, signed.r, signed.s],
      })
    } ...
  })
```

यह सिर्फ एक मानक [viem](https://viem.sh/) ब्लॉकचेन कॉल है।

### स्मार्ट अनुबंध {#smart-contract}

अंत में, [`Greeter.sol`](https://github.com/qbzzt/260301-gasless/blob/main/contracts/src/Greeter.sol) को हस्ताक्षर सत्यापित करने की आवश्यकता है।

```solidity
    constructor(string memory _greeting) {
        greeting = _greeting;

        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256(
                    "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
                ),
                keccak256(bytes("Greeter")),
                keccak256(bytes("1")),
                block.chainid,
                address(this)
            )
        );
    }
```

कंस्ट्रक्टर [डोमेन सेपरेटर](https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator) बनाता है, जो ऊपर दिए गए यूजर इंटरफेस कोड के समान है। ब्लॉकचेन निष्पादन बहुत अधिक महंगा है, इसलिए हम इसकी गणना केवल एक बार करते हैं।

```solidity
    struct GreetingRequest {
        string greeting;
    }
```

यह वह स्ट्रक्चर है जिस पर हस्ताक्षर किए जाते हैं। यहाँ हमारे पास केवल एक फ़ील्ड है।

```solidity
    bytes32 private constant GREETING_TYPEHASH =
        keccak256("GreetingRequest(string greeting)");
```

यह [स्ट्रक्चर आइडेंटिफ़ायर](https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct) है। इसकी गणना हर बार यूजर इंटरफेस में की जाती है।

```solidity
    function sponsoredSetGreeting(
        GreetingRequest calldata req,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
```

यह फ़ंक्शन एक हस्ताक्षरित अनुरोध प्राप्त करता है और अभिवादन को अपडेट करता है।

```solidity
        // EIP-712 डाइजेस्ट की गणना करें
        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                DOMAIN_SEPARATOR,
                keccak256(
                    abi.encode(
                        GREETING_TYPEHASH,
                        keccak256(bytes(req.greeting))
                    )
                )
            )
        );
```

[EIP 712](https://eips.ethereum.org/EIPS/eip-712) के अनुसार डाइजेस्ट (digest) बनाएँ।

```solidity
        // हस्ताक्षरकर्ता को पुनर्प्राप्त करें
        address signer = ecrecover(digest, v, r, s);
        require(signer != address(0), "Invalid signature");
```

हस्ताक्षरकर्ता का पता प्राप्त करने के लिए [`ecrecover`](https://www.evm.codes/precompiled?fork=osaka#0x01) का उपयोग करें। ध्यान दें कि एक खराब हस्ताक्षर के परिणामस्वरूप अभी भी एक वैध पता मिल सकता है, बस वह एक यादृच्छिक (random) पता होगा।

```solidity
        // अभिवादन ऐसे लागू करें जैसे कि हस्ताक्षरकर्ता ने इसे कॉल किया हो
        greeting = req.greeting;
        emit SetGreeting(signer, req.greeting);
    }
```

अभिवादन अपडेट करें।

## भेद्यताएँ (Vulnerabilities) {#vulnerabilities}

यह उत्पादन-स्तर का कोड _नहीं_ है। यह महत्वपूर्ण हमलों के प्रति संवेदनशील है और इसमें प्रमुख विशेषताओं का अभाव है। यहाँ कुछ दिए गए हैं, साथ ही उन्हें हल करने के तरीके भी हैं।

इनमें से कुछ हमलों को देखने के लिए, _Attacks_ शीर्षक के अंतर्गत बटन पर क्लिक करें और देखें कि क्या होता है। **Invalid signature** बटन के लिए, लेन-देन प्रतिक्रिया देखने के लिए सर्वर कंसोल की जाँच करें।

### सर्वर पर डिनायल ऑफ सर्विस (Denial of service) {#dos-on-server}

सबसे आसान हमला सर्वर पर [डिनायल-ऑफ-सर्विस (denial-of-service)](https://en.wikipedia.org/wiki/Denial-of-service_attack) हमला है। सर्वर इंटरनेट पर कहीं से भी अनुरोध प्राप्त करता है और उन अनुरोधों के आधार पर लेन-देन भेजता है। हमलावर को वैध या अमान्य हस्ताक्षरों का एक गुच्छा जारी करने से रोकने के लिए बिल्कुल कुछ भी नहीं है। प्रत्येक एक लेन-देन का कारण बनेगा। अंततः सर्वर के पास गैस का भुगतान करने के लिए ETH खत्म हो जाएगा।

इस समस्या का एक समाधान दर को प्रति ब्लॉक एक लेन-देन तक सीमित करना है। यदि उद्देश्य [बाहरी रूप से स्वामित्व वाले खातों (externally owned accounts)](/developers/docs/accounts/#key-differences) को अभिवादन दिखाना है, तो इससे कोई फर्क नहीं पड़ता कि ब्लॉक के बीच में अभिवादन क्या है।

एक अन्य समाधान पतों का ट्रैक रखना और केवल वैध ग्राहकों के हस्ताक्षरों की अनुमति देना है।

### गलत अभिवादन हस्ताक्षर {#wrong-greeting-sigs}

जब आप **Signature for wrong greeting** पर क्लिक करते हैं, तो आप एक विशिष्ट पते (`0xaA92c5d426430D4769c9E878C1333BDe3d689b3e`) और अभिवादन (`Hello`) के लिए एक वैध हस्ताक्षर सबमिट करते हैं। लेकिन यह इसे एक अलग अभिवादन के साथ सबमिट करता है। यह `ecrecover` को भ्रमित करता है, जो अभिवादन को बदल देता है लेकिन इसमें गलत पता होता है।

इस समस्या को हल करने के लिए, पते को [हस्ताक्षरित स्ट्रक्चर](https://github.com/qbzzt/260301-gasless/blob/main/server/src/Greeter.jsx#L122-L124) में जोड़ें। इस तरह, `ecrecover` यादृच्छिक पता हस्ताक्षर में पते से मेल नहीं खाएगा, और स्मार्ट अनुबंध संदेश को अस्वीकार कर देगा।

### रिप्ले हमले (Replay attacks) {#replay-attack}

जब आप **Replay attack** पर क्लिक करते हैं, तो आप वही "मैं 0xaA92c5d426430D4769c9E878C1333BDe3d689b3e हूँ, और मैं चाहूंगा कि अभिवादन `Hello` हो" हस्ताक्षर सबमिट करते हैं, लेकिन सही अभिवादन के साथ। परिणामस्वरूप, स्मार्ट अनुबंध मानता है कि पते (जो आपका नहीं है) ने अभिवादन को वापस `Hello` में बदल दिया है। ऐसा करने की जानकारी [लेन-देन की जानकारी](https://eth-sepolia.blockscout.com/tx/0xa66afe4bbf886f59533e677a798c802ceab1ac0f9db6e83a4d4b59a45cf7c1b1) में सार्वजनिक रूप से उपलब्ध है।

यदि यह एक समस्या है, तो एक समाधान [नॉन्स](https://en.wikipedia.org/wiki/Cryptographic_nonce) जोड़ना है। पतों और संख्याओं के बीच एक [मैपिंग](https://docs.soliditylang.org/en/latest/types.html#mapping-types) रखें, और हस्ताक्षर में एक नॉन्स फ़ील्ड जोड़ें। यदि नॉन्स फ़ील्ड पते के लिए मैपिंग से मेल खाता है, तो हस्ताक्षर स्वीकार करें और अगली बार के लिए मैपिंग बढ़ाएँ। यदि ऐसा नहीं होता है, तो लेन-देन को अस्वीकार कर दें।

एक अन्य समाधान हस्ताक्षरित डेटा में एक टाइमस्टैम्प जोड़ना है और उस टाइमस्टैम्प के कुछ सेकंड बाद ही हस्ताक्षर को वैध के रूप में स्वीकार करना है। यह सरल और सस्ता है, लेकिन हम समय सीमा के भीतर रिप्ले हमलों का जोखिम उठाते हैं, और यदि समय सीमा पार हो जाती है तो वैध लेन-देन की विफलता का जोखिम होता है।

## अन्य अनुपलब्ध विशेषताएँ {#other-missing-features}

उत्पादन सेटिंग में हम अतिरिक्त विशेषताएँ जोड़ेंगे।

### अन्य सर्वरों से पहुँच {#other-servers}

वर्तमान में, हम किसी भी पते को `sponsorSetGreeting` सबमिट करने की अनुमति देते हैं। विकेंद्रीकरण के हित में, यह बिल्कुल वही हो सकता है जो हम चाहते हैं। या हो सकता है कि हम यह सुनिश्चित करना चाहें कि प्रायोजित लेन-देन _हमारे_ सर्वर के माध्यम से हों, जिस स्थिति में हम स्मार्ट अनुबंध में `msg.sender` की जाँच करेंगे।

किसी भी तरह से, यह एक सचेत डिज़ाइन निर्णय होना चाहिए, न कि केवल इस मुद्दे के बारे में न सोचने का परिणाम।

### त्रुटि प्रबंधन (Error handling) {#error-handling}

एक उपयोगकर्ता एक अभिवादन सबमिट करता है। हो सकता है कि यह अगले ब्लॉक में अपडेट हो जाए। हो सकता है कि ऐसा न हो। त्रुटियाँ अदृश्य होती हैं। उत्पादन सिस्टम पर, उपयोगकर्ता को इन मामलों के बीच अंतर करने में सक्षम होना चाहिए:

- नया अभिवादन अभी तक सबमिट नहीं किया गया है
- नया अभिवादन सबमिट कर दिया गया है, और यह प्रक्रिया में है
- नया अभिवादन अस्वीकार कर दिया गया है

## निष्कर्ष {#conclusion}

इस बिंदु पर, आपको कुछ केंद्रीकरण की कीमत पर, अपने विकेंद्रीकृत एप्लिकेशन (dapp) उपयोगकर्ताओं के लिए एक गैस-मुक्त अनुभव बनाने में सक्षम होना चाहिए।

हालाँकि, यह केवल उन स्मार्ट अनुबंधों के साथ काम करता है जो ERC-712 का समर्थन करते हैं। उदाहरण के लिए, किसी ERC-20 टोकन को ट्रांसफर करने के लिए, यह आवश्यक है कि लेन-देन पर केवल एक संदेश के बजाय मालिक द्वारा हस्ताक्षर किए जाएं। सबसे सरल समाधान यह है कि संपत्तियों का स्वामित्व EOA पते के पास न होकर, एक अलग अनुबंध ([खाता अमूर्तन](/roadmap/account-abstraction/) का एक सरल रूप) के पास हो। आप इसके बारे में [अगले ट्यूटोरियल में](/developers/tutorials/gasless-token) अधिक पढ़ सकते हैं।

[मेरे और काम यहाँ देखें](https://cryptodocguy.pro/)।
