मुख्य सामग्री पर जाएँ
Change page

स्मार्ट अनुबंधों की संरचना

पेज का अंतिम अपडेट: 23 फ़रवरी 2026

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

पूर्वापेक्षाएं

पहले सुनिश्चित करें कि आपने स्मार्ट अनुबंधों के बारे में पढ़ा है। यह दस्तावेज़ मानता है कि आप जावास्क्रिप्ट या पायथन जैसी प्रोग्रामिंग भाषाओं से पहले से ही परिचित हैं।

डेटा

किसी भी अनुबंध डेटा को एक स्थान पर निर्दिष्ट किया जाना चाहिए: या तो storage या memory पर। स्मार्ट अनुबंध में भंडारण को संशोधित करना महंगा है, इसलिए आपको यह विचार करने की आवश्यकता है कि आपका डेटा कहां रहना चाहिए।

भंडारण

लगातार डेटा को भंडारण के रूप में संदर्भित किया जाता है और इसे स्टेट वेरिएबल्स द्वारा दर्शाया जाता है। ये मान ब्लॉकचेन पर स्थायी रूप से संग्रहित हो जाते हैं। आपको प्रकार घोषित करने की आवश्यकता है ताकि अनुबंध इस बात पर नज़र रख सके कि संकलित होने पर ब्लॉकचेन पर उसे कितने भंडारण की आवश्यकता है।

1// Solidity उदाहरण
2contract SimpleStorage {
3 uint storedData; // स्टेट वैरिएबल
4 // ...
5}
1# Vyper उदाहरण
2storedData: int128

यदि आपने पहले से ही ऑब्जेक्ट-ओरिएंटेड भाषाओं को प्रोग्राम किया है, तो आप संभवतः अधिकांश प्रकारों से परिचित होंगे। हालांकि, यदि आप एथेरियम विकास में नए हैं तो address आपके लिए नया होना चाहिए।

एक address प्रकार एक एथेरियम पता रख सकता है जो 20 बाइट्स या 160 बिट्स के बराबर होता है। यह हेक्साडेसिमल नोटेशन में अग्रणी 0x के साथ लौटता है।

अन्य प्रकारों में शामिल हैं:

  • बूलियन
  • पूर्णांक
  • निश्चित बिंदु संख्याएँ
  • निश्चित आकार की बाइट सरणियाँ
  • गतिशील आकार की बाइट सरणियाँ
  • परिमेय और पूर्णांक लिटरल
  • स्ट्रिंग लिटरल
  • हेक्साडेसिमल लिटरल
  • एनम्स

अधिक स्पष्टीकरण के लिए, दस्तावेज़ों पर एक नज़र डालें:

मेमोरी

मान जो केवल अनुबंध फंक्शन के निष्पादन के जीवनकाल के लिए संग्रहित होते हैं, उन्हें मेमोरी वेरिएबल्स कहा जाता है। चूंकि ये ब्लॉकचेन पर स्थायी रूप से संग्रहित नहीं होते हैं, इसलिए इनका उपयोग करना बहुत सस्ता होता है।

सॉलिडिटी डॉक्स (opens in a new tab) में EVM डेटा (स्टोरेज, मेमोरी और स्टैक) कैसे संग्रहीत करता है, इसके बारे में अधिक जानें।

पर्यावरण वैरिएबल

आपके अनुबंध पर आपके द्वारा परिभाषित वेरिएबल्स के अलावा, कुछ विशेष वैश्विक वेरिएबल्स हैं। वे मुख्य रूप से ब्लॉकचेन या वर्तमान लेनदेन के बारे में जानकारी प्रदान करने के लिए उपयोग किए जाते हैं।

उदाहरण

प्रॉपस्टेट वेरिएबलविवरण
block.timestampuint256वर्तमान ब्लॉक युग टाइमस्टैम्प
msg.senderपतासंदेश का प्रेषक (वर्तमान कॉल)

फ़ंक्शन

सबसे सरल शब्दों में, फंक्शंस आने वाले लेनदेन के जवाब में जानकारी प्राप्त कर सकते हैं या जानकारी सेट कर सकते हैं।

फंक्शन कॉल दो प्रकार के होते हैं:

  • internal – ये EVM कॉल नहीं बनाते हैं
    • आंतरिक फ़ंक्शन और स्टेट वैरिएबल को केवल आंतरिक रूप से एक्सेस किया जा सकता है (यानी, वर्तमान अनुबंध या इससे प्राप्त होने वाले अनुबंधों के भीतर से)
  • external – ये EVM कॉल बनाते हैं
    • बाहरी फंक्शंस अनुबंध इंटरफ़ेस का हिस्सा हैं, जिसका अर्थ है कि उन्हें अन्य अनुबंधों से और लेनदेन के माध्यम से कॉल किया जा सकता है। एक बाहरी फ़ंक्शन f को आंतरिक रूप से कॉल नहीं किया जा सकता है (यानी, f() काम नहीं करता है, लेकिन this.f() काम करता है)।

वे public या private भी हो सकते हैं

  • public फ़ंक्शन को अनुबंध के भीतर से आंतरिक रूप से या संदेशों के माध्यम से बाहरी रूप से कॉल किया जा सकता है
  • private फ़ंक्शन केवल उस अनुबंध के लिए दिखाई देते हैं जिसमें उन्हें परिभाषित किया गया है और व्युत्पन्न अनुबंधों में नहीं

दोनों फंक्शंस और स्टेट वेरिएबल्स को सार्वजनिक या निजी बनाया जा सकता है

अनुबंध पर एक स्टेट वेरिएबल्स को अपडेट करने के लिए एक फंक्शन यहां है:

1// Solidity उदाहरण
2function update_name(string value) public {
3 dapp_name = value;
4}
  • प्रकार string का पैरामीटर value फ़ंक्शन: update_name में पास किया जाता है
  • इसे public घोषित किया गया है, जिसका अर्थ है कि कोई भी इसे एक्सेस कर सकता है
  • इसे view घोषित नहीं किया गया है, इसलिए यह अनुबंध की स्थिति को संशोधित कर सकता है

व्यू फ़ंक्शन

ये फंक्शंस अनुबंध के डेटा की स्थिति को संशोधित नहीं करने का वादा करते हैं। सामान्य उदाहरण "गेटर" फंक्शंस हैं – उदाहरण के लिए आप इसका उपयोग यूज़र की शेष राशि प्राप्त करने के लिए कर सकते हैं।

1// Solidity उदाहरण
2function balanceOf(address _owner) public view returns (uint256 _balance) {
3 return ownerPizzaCount[_owner];
4}
1dappName: public(string)
2
3@view
4@public
5def readName() -> string:
6 return dappName

संशोधित स्थिति क्या मानी जाती है:

  1. स्टेट वेरिएबल्स के लिए लेखन।
  2. इवेंट्स उत्सर्जित करना (opens in a new tab)
  3. अन्य अनुबंध बनाना (opens in a new tab)
  4. selfdestruct का उपयोग करना।
  5. कॉल के माध्यम से ईथर भेजना।
  6. किसी भी ऐसे फ़ंक्शन को कॉल करना जो view या pure के रूप में चिह्नित नहीं है।
  7. निम्न-स्तरीय कॉल का उपयोग करना।
  8. इनलाइन असेंबली का उपयोग करना जिसमें कुछ ऑप्कोड होते हैं।

कंस्ट्रक्टर फ़ंक्शन

constructor फ़ंक्शन केवल एक बार निष्पादित होते हैं जब अनुबंध पहली बार परिनियोजित होता है। कई वर्ग-आधारित प्रोग्रामिंग भाषाओं में constructor की तरह, ये फ़ंक्शन अक्सर स्टेट वैरिएबल को उनके निर्दिष्ट मानों पर प्रारंभ करते हैं।

1// Solidity उदाहरण
2// अनुबंध के डेटा को प्रारंभ करता है, `owner` को
3// अनुबंध निर्माता के पते पर सेट करता है।
4constructor() public {
5 // सभी स्मार्ट अनुबंध अपने कार्यों को ट्रिगर करने के लिए बाहरी लेनदेन पर निर्भर करते हैं।
6 // `msg` एक वैश्विक वैरिएबल है जिसमें दिए गए लेनदेन पर प्रासंगिक डेटा शामिल है,
7 // जैसे प्रेषक का पता और लेनदेन में शामिल ETH मान।
8 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
9 owner = msg.sender;
10}
सभी दिखाएँ
1# Vyper उदाहरण
2
3@external
4def __init__(_beneficiary: address, _bidding_time: uint256):
5 self.beneficiary = _beneficiary
6 self.auctionStart = block.timestamp
7 self.auctionEnd = self.auctionStart + _bidding_time

बिल्ट-इन फ़ंक्शन

आपके अनुबंध पर आपके द्वारा परिभाषित वेरिएबल्स और फंक्शंस के अलावा, कुछ विशेष बिल्ट-इन फंक्शंस हैं। सबसे स्पष्ट उदाहरण है:

  • address.send() – सॉलिडिटी
  • send(address) – वाइपर

ये अनुबंधों को ETH को अन्य खातों में भेजने की अनुमति देते हैं।

फ़ंक्शन लिखना

आपका फंक्शन निम्न आवश्यक करता है:

  • पैरामीटर वेरिएबल और प्रकार (यदि यह पैरामीटर स्वीकार करता है)
  • internal/external की घोषणा
  • pure/view/payable की घोषणा
  • रिटर्न प्रकार (यदि यह मान लौटाता है)
1pragma solidity >=0.4.0 <=0.6.0;
2
3contract ExampleDapp {
4 string dapp_name; // state variable
5
6 // जब अनुबंध परिनियोजित होता है और मान को प्रारंभ करता है तब कॉल किया जाता है
7 constructor() public {
8 dapp_name = "My Example dapp";
9 }
10
11 // फ़ंक्शन प्राप्त करें
12 function read_name() public view returns(string) {
13 return dapp_name;
14 }
15
16 // फ़ंक्शन सेट करें
17 function update_name(string value) public {
18 dapp_name = value;
19 }
20}
सभी दिखाएँ

एक पूर्ण अनुबंध कुछ इस तरह दिख सकता है। यहाँ constructor फ़ंक्शन dapp_name वैरिएबल के लिए एक प्रारंभिक मान प्रदान करता है।

इवेंट्स और लॉग

इवेंट्स आपके स्मार्ट अनुबंध को आपके फ़्रंटएंड या अन्य सदस्यता लेने वाले एप्लिकेशन के साथ संवाद करने में सक्षम बनाते हैं। एक बार लेनदेन मान्य हो जाने और एक ब्लॉक में जोड़े जाने के बाद, स्मार्ट अनुबंध इवेंट्स का उत्सर्जन कर सकते हैं और जानकारी लॉग कर सकते हैं, जिसे फ्रंटएंड तब संसाधित और उपयोग कर सकता है।

एनोटेट किए गए उदाहरण

ये सॉलिडिटी में लिखे गए कुछ उदाहरण हैं। यदि आप कोड के साथ खेलना चाहते हैं, तो आप रीमिक्स (opens in a new tab) में उनके साथ इंटरैक्ट कर सकते हैं।

हैलो वर्ल्ड

1// सिमेंटिक वर्जनिंग का उपयोग करते हुए, Solidity का संस्करण निर्दिष्ट करता है।
2// और जानें: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
3pragma solidity ^0.5.10;
4
5// `HelloWorld` नामक एक अनुबंध को परिभाषित करता है।
6// एक अनुबंध फ़ंक्शन और डेटा (इसकी स्थिति) का एक संग्रह है।
7// एक बार परिनियोजित होने के बाद, एक अनुबंध Ethereum ब्लॉकचेन पर एक विशिष्ट पते पर रहता है।
8// और जानें: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html
9contract HelloWorld {
10
11 // `string` प्रकार के एक स्टेट वैरिएबल `message` की घोषणा करता है।
12 // स्टेट वैरिएबल ऐसे वैरिएबल होते हैं जिनके मान अनुबंध भंडारण में स्थायी रूप से संग्रहीत होते हैं।
13 // कीवर्ड `public` वैरिएबल को एक अनुबंध के बाहर से सुलभ बनाता है
14 // और एक फ़ंक्शन बनाता है जिसे अन्य अनुबंध या क्लाइंट मान तक पहुंचने के लिए कॉल कर सकते हैं।
15 string public message;
16
17 // कई वर्ग-आधारित ऑब्जेक्ट-ओरिएंटेड भाषाओं के समान, एक कंस्ट्रक्टर
18 // एक विशेष फ़ंक्शन है जो केवल अनुबंध निर्माण पर निष्पादित होता है।
19 // कंस्ट्रक्टर का उपयोग अनुबंध के डेटा को प्रारंभ करने के लिए किया जाता है।
20 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
21 constructor(string memory initMessage) public {
22 // एक स्ट्रिंग तर्क `initMessage` स्वीकार करता है और मान सेट करता है
23 // अनुबंध के `message` भंडारण वैरिएबल में)।
24 message = initMessage;
25 }
26
27 // एक सार्वजनिक फ़ंक्शन जो एक स्ट्रिंग तर्क स्वीकार करता है
28 // और `message` भंडारण वैरिएबल को अपडेट करता है।
29 function update(string memory newMessage) public {
30 message = newMessage;
31 }
32}
सभी दिखाएँ

टोकन

1pragma solidity ^0.5.10;
2
3contract Token {
4 // एक `address` एक ईमेल पते के बराबर है - इसका उपयोग Ethereum पर एक खाते की पहचान करने के लिए किया जाता है।
5 // पते एक स्मार्ट अनुबंध या बाहरी (उपयोगकर्ता) खातों का प्रतिनिधित्व कर सकते हैं।
6 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/types.html#address
7 address public owner;
8
9 // एक `mapping` अनिवार्य रूप से एक हैश टेबल डेटा संरचना है।
10 // यह `mapping` एक अहस्ताक्षरित पूर्णांक (टोकन शेष) को एक पते (टोकन धारक) को निर्दिष्ट करता है।
11 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types
12 mapping (address => uint) public balances;
13
14 // इवेंट्स ब्लॉकचेन पर गतिविधि की लॉगिंग की अनुमति देते हैं।
15 // अनुबंध की स्थिति में परिवर्तन पर प्रतिक्रिया करने के लिए Ethereum क्लाइंट इवेंट्स सुन सकते हैं।
16 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events
17 event Transfer(address from, address to, uint amount);
18
19 // अनुबंध के डेटा को प्रारंभ करता है, `owner` को
20 // अनुबंध निर्माता के पते पर सेट करता है।
21 constructor() public {
22 // सभी स्मार्ट अनुबंध अपने कार्यों को ट्रिगर करने के लिए बाहरी लेनदेन पर निर्भर करते हैं।
23 // `msg` एक वैश्विक वैरिएबल है जिसमें दिए गए लेनदेन पर प्रासंगिक डेटा शामिल है,
24 // जैसे प्रेषक का पता और लेनदेन में शामिल ETH मान।
25 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
26 owner = msg.sender;
27 }
28
29 // नए टोकन की एक राशि बनाता है और उन्हें एक पते पर भेजता है।
30 function mint(address receiver, uint amount) public {
31 // `require` एक नियंत्रण संरचना है जिसका उपयोग कुछ शर्तों को लागू करने के लिए किया जाता है।
32 // यदि कोई `require` कथन `false` का मूल्यांकन करता है, तो एक अपवाद चालू हो जाता है,
33 // जो वर्तमान कॉल के दौरान स्थिति में किए गए सभी परिवर्तनों को वापस कर देता है।
34 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
35
36 // केवल अनुबंध का मालिक ही इस फ़ंक्शन को कॉल कर सकता है
37 require(msg.sender == owner, "You are not the owner.");
38
39 // टोकन की अधिकतम राशि लागू करता है
40 require(amount < 1e60, "Maximum issuance exceeded");
41
42 // `receiver` की शेष राशि को `amount` से बढ़ाता है
43 balances[receiver] += amount;
44 }
45
46 // किसी भी कॉलर से मौजूदा टोकन की एक राशि एक पते पर भेजता है।
47 function transfer(address receiver, uint amount) public {
48 // प्रेषक के पास भेजने के लिए पर्याप्त टोकन होने चाहिए
49 require(amount <= balances[msg.sender], "Insufficient balance.");
50
51 // दो पतों के टोकन शेष को समायोजित करता है
52 balances[msg.sender] -= amount;
53 balances[receiver] += amount;
54
55 // पहले परिभाषित इवेंट का उत्सर्जन करता है
56 emit Transfer(msg.sender, receiver, amount);
57 }
58}
सभी दिखाएँ

अद्वितीय डिजिटल संपत्ति

1pragma solidity ^0.5.10;
2
3// अन्य फ़ाइलों से प्रतीकों को वर्तमान अनुबंध में आयात करता है।
4// इस मामले में, OpenZeppelin से सहायक अनुबंधों की एक श्रृंखला।
5// और जानें: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#importing-other-source-files
6
7import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol";
8import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
9import "../node_modules/@openzeppelin/contracts/introspection/ERC165.sol";
10import "../node_modules/@openzeppelin/contracts/math/SafeMath.sol";
11
12// `is` कीवर्ड का उपयोग बाहरी अनुबंधों से कार्यों और कीवर्ड को विरासत में लेने के लिए किया जाता है।
13// इस मामले में, `CryptoPizza` `IERC721` और `ERC165` अनुबंधों से विरासत में मिला है।
14// और जानें: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance
15contract CryptoPizza is IERC721, ERC165 {
16 // अंकगणितीय संचालन को सुरक्षित रूप से करने के लिए OpenZeppelin की SafeMath लाइब्रेरी का उपयोग करता है।
17 // और जानें: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath
18 using SafeMath for uint256;
19
20 // Solidity में लगातार स्टेट वैरिएबल अन्य भाषाओं के समान हैं
21 // लेकिन आपको एक ऐसे एक्सप्रेशन से असाइन करना होगा जो कंपाइल समय पर स्थिर हो।
22 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constant-state-variables
23 uint256 constant dnaDigits = 10;
24 uint256 constant dnaModulus = 10 ** dnaDigits;
25 bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
26
27 // स्ट्रक्ट प्रकार आपको अपना स्वयं का प्रकार परिभाषित करने देते हैं
28 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs
29 struct Pizza {
30 string name;
31 uint256 dna;
32 }
33
34 // पिज्जा स्ट्रक्ट्स की एक खाली सरणी बनाता है
35 Pizza[] public pizzas;
36
37 // पिज्जा आईडी से उसके मालिक के पते तक मैपिंग
38 mapping(uint256 => address) public pizzaToOwner;
39
40 // मालिक के पते से स्वामित्व वाले टोकन की संख्या तक मैपिंग
41 mapping(address => uint256) public ownerPizzaCount;
42
43 // टोकन आईडी से स्वीकृत पते पर मैपिंग
44 mapping(uint256 => address) pizzaApprovals;
45
46 // आप मैपिंग को नेस्ट कर सकते हैं, यह उदाहरण ऑपरेटर अनुमोदन के लिए मालिक को मैप करता है
47 mapping(address => mapping(address => bool)) private operatorApprovals;
48
49 // स्ट्रिंग (नाम) और डीएनए से एक यादृच्छिक पिज्जा बनाने के लिए आंतरिक फ़ंक्शन
50 function _createPizza(string memory _name, uint256 _dna)
51 // `internal` कीवर्ड का मतलब है कि यह फ़ंक्शन केवल
52 // इस अनुबंध और इस अनुबंध को प्राप्त करने वाले अनुबंधों के भीतर दिखाई देता है
53 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters
54 internal
55 // `isUnique` एक फ़ंक्शन संशोधक है जो जांचता है कि पिज्जा पहले से मौजूद है या नहीं
56 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers
57 isUnique(_name, _dna)
58 {
59 // पिज्जा की सरणी में पिज्जा जोड़ता है और आईडी प्राप्त करता है
60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);
61
62 // जांचता है कि पिज्जा का मालिक वर्तमान उपयोगकर्ता के समान है
63 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
64
65 // ध्यान दें कि address(0) शून्य पता है,
66 // यह दर्शाता है कि pizza[id] अभी तक किसी विशेष उपयोगकर्ता को आवंटित नहीं किया गया है।
67
68 assert(pizzaToOwner[id] == address(0));
69
70 // पिज्जा को मालिक से मैप करता है
71 pizzaToOwner[id] = msg.sender;
72 ownerPizzaCount[msg.sender] = SafeMath.add(
73 ownerPizzaCount[msg.sender],
74 1
75 );
76 }
77
78 // स्ट्रिंग (नाम) से एक यादृच्छिक पिज्जा बनाता है
79 function createRandomPizza(string memory _name) public {
80 uint256 randDna = generateRandomDna(_name, msg.sender);
81 _createPizza(_name, randDna);
82 }
83
84 // स्ट्रिंग (नाम) और मालिक (निर्माता) के पते से यादृच्छिक डीएनए उत्पन्न करता है
85 function generateRandomDna(string memory _str, address _owner)
86 public
87 // `pure` के रूप में चिह्नित फ़ंक्शन स्थिति से पढ़ने या संशोधित न करने का वादा करते हैं
88 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions
89 pure
90 returns (uint256)
91 {
92 // स्ट्रिंग (नाम) + पता (मालिक) से यादृच्छिक uint उत्पन्न करता है
93 uint256 rand = uint256(keccak256(abi.encodePacked(_str))) +
94 uint256(_owner);
95 rand = rand % dnaModulus;
96 return rand;
97 }
98
99 // मालिक द्वारा पाए गए पिज्जा की सरणी लौटाता है
100 function getPizzasByOwner(address _owner)
101 public
102 // `view` के रूप में चिह्नित फ़ंक्शन स्थिति को संशोधित न करने का वादा करते हैं
103 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions
104 view
105 returns (uint256[] memory)
106 {
107 // केवल इस फ़ंक्शन कॉल के जीवनचक्र के लिए मानों को संग्रहीत करने के लिए `memory` भंडारण स्थान का उपयोग करता है।
108 // और जानें: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack
109 uint256[] memory result = new uint256[](ownerPizzaCount[_owner]);
110 uint256 counter = 0;
111 for (uint256 i = 0; i < pizzas.length; i++) {
112 if (pizzaToOwner[i] == _owner) {
113 result[counter] = i;
114 counter++;
115 }
116 }
117 return result;
118 }
119
120 // पिज्जा और स्वामित्व को दूसरे पते पर स्थानांतरित करता है
121 function transferFrom(address _from, address _to, uint256 _pizzaId) public {
122 require(_from != address(0) && _to != address(0), "Invalid address.");
123 require(_exists(_pizzaId), "Pizza does not exist.");
124 require(_from != _to, "Cannot transfer to the same address.");
125 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
126
127 ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1);
128 ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1);
129 pizzaToOwner[_pizzaId] = _to;
130
131 // आयातित IERC721 अनुबंध में परिभाषित इवेंट का उत्सर्जन करता है
132 emit Transfer(_from, _to, _pizzaId);
133 _clearApproval(_to, _pizzaId);
134 }
135
136 /**
137 * किसी दिए गए टोकन आईडी के स्वामित्व को सुरक्षित रूप से दूसरे पते पर स्थानांतरित करता है
138 * यदि लक्ष्य पता एक अनुबंध है, तो इसे `onERC721Received` लागू करना होगा,
139 * जिसे एक सुरक्षित हस्तांतरण पर कहा जाता है, और जादू मान
140 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` लौटाता है;
141 * अन्यथा, हस्तांतरण वापस कर दिया जाता है।
142 */
143 function safeTransferFrom(address from, address to, uint256 pizzaId)
144 public
145 {
146 // solium-disable-next-line arg-overflow
147 this.safeTransferFrom(from, to, pizzaId, "");
148 }
149
150 /**
151 * किसी दिए गए टोकन आईडी के स्वामित्व को सुरक्षित रूप से दूसरे पते पर स्थानांतरित करता है
152 * यदि लक्ष्य पता एक अनुबंध है, तो इसे `onERC721Received` लागू करना होगा,
153 * जिसे एक सुरक्षित हस्तांतरण पर कहा जाता है, और जादू मान
154 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` लौटाता है;
155 * अन्यथा, हस्तांतरण वापस कर दिया जाता है।
156 */
157 function safeTransferFrom(
158 address from,
159 address to,
160 uint256 pizzaId,
161 bytes memory _data
162 ) public {
163 this.transferFrom(from, to, pizzaId);
164 require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implement onERC721Received.");
165 }
166
167 /**
168 * किसी लक्ष्य पते पर `onERC721Received` को लागू करने के लिए आंतरिक फ़ंक्शन
169 * यदि लक्ष्य पता एक अनुबंध नहीं है तो कॉल निष्पादित नहीं किया जाता है
170 */
171 function _checkOnERC721Received(
172 address from,
173 address to,
174 uint256 pizzaId,
175 bytes memory _data
176 ) internal returns (bool) {
177 if (!isContract(to)) {
178 return true;
179 }
180
181 bytes4 retval = IERC721Receiver(to).onERC721Received(
182 msg.sender,
183 from,
184 pizzaId,
185 _data
186 );
187 return (retval == _ERC721_RECEIVED);
188 }
189
190 // एक पिज्जा को जलाता है - टोकन को पूरी तरह से नष्ट कर देता है
191 // `external` फ़ंक्शन संशोधक का मतलब है कि यह फ़ंक्शन
192 // अनुबंध इंटरफ़ेस का हिस्सा है और अन्य अनुबंध इसे कॉल कर सकते हैं
193 function burn(uint256 _pizzaId) external {
194 require(msg.sender != address(0), "Invalid address.");
195 require(_exists(_pizzaId), "Pizza does not exist.");
196 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
197
198 ownerPizzaCount[msg.sender] = SafeMath.sub(
199 ownerPizzaCount[msg.sender],
200 1
201 );
202 pizzaToOwner[_pizzaId] = address(0);
203 }
204
205 // पते द्वारा पिज्जा की गिनती लौटाता है
206 function balanceOf(address _owner) public view returns (uint256 _balance) {
207 return ownerPizzaCount[_owner];
208 }
209
210 // आईडी द्वारा पाए गए पिज्जा के मालिक को लौटाता है
211 function ownerOf(uint256 _pizzaId) public view returns (address _owner) {
212 address owner = pizzaToOwner[_pizzaId];
213 require(owner != address(0), "Invalid Pizza ID.");
214 return owner;
215 }
216
217 // पिज्जा के स्वामित्व को स्थानांतरित करने के लिए दूसरे पते को मंजूरी देता है
218 function approve(address _to, uint256 _pizzaId) public {
219 require(msg.sender == pizzaToOwner[_pizzaId], "Must be the Pizza owner.");
220 pizzaApprovals[_pizzaId] = _to;
221 emit Approval(msg.sender, _to, _pizzaId);
222 }
223
224 // विशिष्ट पिज्जा के लिए स्वीकृत पता लौटाता है
225 function getApproved(uint256 _pizzaId)
226 public
227 view
228 returns (address operator)
229 {
230 require(_exists(_pizzaId), "Pizza does not exist.");
231 return pizzaApprovals[_pizzaId];
232 }
233
234 /**
235 * किसी दिए गए टोकन आईडी की वर्तमान स्वीकृति को साफ़ करने के लिए निजी फ़ंक्शन
236 * यदि दिया गया पता वास्तव में टोकन का स्वामी नहीं है तो रिवर्ट करता है
237 */
238 function _clearApproval(address owner, uint256 _pizzaId) private {
239 require(pizzaToOwner[_pizzaId] == owner, "Must be pizza owner.");
240 require(_exists(_pizzaId), "Pizza does not exist.");
241 if (pizzaApprovals[_pizzaId] != address(0)) {
242 pizzaApprovals[_pizzaId] = address(0);
243 }
244 }
245
246 /*
247 * किसी दिए गए ऑपरेटर की स्वीकृति को सेट या अनसेट करता है
248 * एक ऑपरेटर को उनकी ओर से प्रेषक के सभी टोकन स्थानांतरित करने की अनुमति है
249 */
250 function setApprovalForAll(address to, bool approved) public {
251 require(to != msg.sender, "Cannot approve own address");
252 operatorApprovals[msg.sender][to] = approved;
253 emit ApprovalForAll(msg.sender, to, approved);
254 }
255
256 // बताता है कि क्या कोई ऑपरेटर किसी दिए गए मालिक द्वारा अनुमोदित है
257 function isApprovedForAll(address owner, address operator)
258 public
259 view
260 returns (bool)
261 {
262 return operatorApprovals[owner][operator];
263 }
264
265 // पिज्जा का स्वामित्व लेता है - केवल स्वीकृत उपयोगकर्ताओं के लिए
266 function takeOwnership(uint256 _pizzaId) public {
267 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
268 address owner = this.ownerOf(_pizzaId);
269 this.transferFrom(owner, msg.sender, _pizzaId);
270 }
271
272 // जांचता है कि पिज्जा मौजूद है या नहीं
273 function _exists(uint256 pizzaId) internal view returns (bool) {
274 address owner = pizzaToOwner[pizzaId];
275 return owner != address(0);
276 }
277
278 // जांचता है कि पता मालिक है या पिज्जा स्थानांतरित करने के लिए अनुमोदित है
279 function _isApprovedOrOwner(address spender, uint256 pizzaId)
280 internal
281 view
282 returns (bool)
283 {
284 address owner = pizzaToOwner[pizzaId];
285 // Solium जांच अक्षम करें क्योंकि
286 // https://github.com/duaraghav8/Solium/issues/175
287 // solium-disable-next-line operator-whitespace
288 return (spender == owner ||
289 this.getApproved(pizzaId) == spender ||
290 this.isApprovedForAll(owner, spender));
291 }
292
293 // जांचें कि पिज्जा अद्वितीय है और अभी तक मौजूद नहीं है
294 modifier isUnique(string memory _name, uint256 _dna) {
295 bool result = true;
296 for (uint256 i = 0; i < pizzas.length; i++) {
297 if (
298 keccak256(abi.encodePacked(pizzas[i].name)) ==
299 keccak256(abi.encodePacked(_name)) &&
300 pizzas[i].dna == _dna
301 ) {
302 result = false;
303 }
304 }
305 require(result, "Pizza with such name already exists.");
306 _;
307 }
308
309 // लौटाता है कि लक्ष्य पता एक अनुबंध है या नहीं
310 function isContract(address account) internal view returns (bool) {
311 uint256 size;
312 // वर्तमान में यह जांचने का कोई बेहतर तरीका नहीं है कि किसी पते में कोई अनुबंध है या नहीं
313 // उस पते पर कोड के आकार की जांच करने से।
314 // यह कैसे काम करता है, इसके बारे में अधिक जानकारी के लिए https://ethereum.stackexchange.com/a/14016/36603
315 // देखें।
316 // TODO Serenity रिलीज से पहले इसे फिर से जांचें, क्योंकि तब सभी पते
317 // अनुबंध होंगे।
318 // solium-disable-next-line security/no-inline-assembly
319 assembly {
320 size := extcodesize(account)
321 }
322 return size > 0;
323 }
324}
सभी दिखाएँ

आगे की रीडिंग

स्मार्ट अनुबंधों के अधिक संपूर्ण अवलोकन के लिए सॉलिडिटी और वाइपर के प्रलेखन देखें:

क्या यह लेख सहायक था?