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

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

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

आवश्यक शर्तें

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

डेटा

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

स्टोरेज

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

1// Solidity example
2contract SimpleStorage {
3 uint storedData; // State variable
4 // ...
5}
कॉपी करें
1# Vyper example
2storedData: int128
कॉपी करें

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

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

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

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

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

मेमोरी

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

EVM डेटा (भंडारण, मेमोरी और स्टैक) को Solidity डॉक्स(opens in a new tab) में कैसे स्टोर करता है, इसके बारे में और जानें।

परिवेश वेरिएबल

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

उदाहरण

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

फंक्शंस

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

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

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

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

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

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

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

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

फंक्शंस देखें

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

1// Solidity example
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. आत्मविनाश का उपयोग करना।
  5. कॉल के माध्यम से ईथर भेजना।
  6. किसी भी फंक्शन को कॉल करना जो view या pure चिह्नित नहीं है।
  7. निम्न-स्तरीय कॉल का उपयोग करना।
  8. इनलाइन असेंबली का उपयोग करना जिसमें कुछ ऑप्कोड होते हैं।

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

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

1// Solidity example
2// Initializes the contract's data, setting the `owner`
3// to the address of the contract creator.
4constructor() public {
5 // All smart contracts rely on external transactions to trigger its functions.
6 // `msg` is a global variable that includes relevant data on the given transaction,
7 // such as the address of the sender and the ETH value included in the transaction.
8 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
9 owner = msg.sender;
10}
सभी दिखाएँ
कॉपी करें
1# Vyper example
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() – Solidity
  • send(address) – Vyper

ये अनुबंधों को 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 // Called when the contract is deployed and initializes the value
7 constructor() public {
8 dapp_name = "My Example dapp";
9 }
10
11 // Get Function
12 function read_name() public view returns(string) {
13 return dapp_name;
14 }
15
16 // Set Function
17 function update_name(string value) public {
18 dapp_name = value;
19 }
20}
सभी दिखाएँ
कॉपी करें

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

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

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

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

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

हैलो वर्ल्ड

1// Specifies the version of Solidity, using semantic versioning.
2// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
3pragma solidity ^0.5.10;
4
5// Defines a contract named `HelloWorld`.
6// A contract is a collection of functions and data (its state).
7// Once deployed, a contract resides at a specific address on the Ethereum blockchain.
8// Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html
9contract HelloWorld {
10
11 // Declares a state variable `message` of type `string`.
12 // State variables are variables whose values are permanently stored in contract storage.
13 // The keyword `public` makes variables accessible from outside a contract
14 // and creates a function that other contracts or clients can call to access the value.
15 string public message;
16
17 // Similar to many class-based object-oriented languages, a constructor is
18 // a special function that is only executed upon contract creation.
19 // Constructors are used to initialize the contract's data.
20 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
21 constructor(string memory initMessage) public {
22 // Accepts a string argument `initMessage` and sets the value
23 // into the contract's `message` storage variable).
24 message = initMessage;
25 }
26
27 // A public function that accepts a string argument
28 // and updates the `message` storage variable.
29 function update(string memory newMessage) public {
30 message = newMessage;
31 }
32}
सभी दिखाएँ
कॉपी करें

टोकन

1pragma solidity ^0.5.10;
2
3contract Token {
4 // An `address` is comparable to an email address - it's used to identify an account on Ethereum.
5 // Addresses can represent a smart contract or an external (user) accounts.
6 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/types.html#address
7 address public owner;
8
9 // A `mapping` is essentially a hash table data structure.
10 // This `mapping` assigns an unsigned integer (the token balance) to an address (the token holder).
11 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types
12 mapping (address => uint) public balances;
13
14 // Events allow for logging of activity on the blockchain.
15 // Ethereum clients can listen for events in order to react to contract state changes.
16 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events
17 event Transfer(address from, address to, uint amount);
18
19 // Initializes the contract's data, setting the `owner`
20 // to the address of the contract creator.
21 constructor() public {
22 // All smart contracts rely on external transactions to trigger its functions.
23 // `msg` is a global variable that includes relevant data on the given transaction,
24 // such as the address of the sender and the ETH value included in the transaction.
25 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties
26 owner = msg.sender;
27 }
28
29 // Creates an amount of new tokens and sends them to an address.
30 function mint(address receiver, uint amount) public {
31 // `require` is a control structure used to enforce certain conditions.
32 // If a `require` statement evaluates to `false`, an exception is triggered,
33 // which reverts all changes made to the state during the current call.
34 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
35
36 // Only the contract owner can call this function
37 require(msg.sender == owner, "You are not the owner.");
38
39 // Enforces a maximum amount of tokens
40 require(amount < 1e60, "Maximum issuance exceeded");
41
42 // Increases the balance of `receiver` by `amount`
43 balances[receiver] += amount;
44 }
45
46 // Sends an amount of existing tokens from any caller to an address.
47 function transfer(address receiver, uint amount) public {
48 // The sender must have enough tokens to send
49 require(amount <= balances[msg.sender], "Insufficient balance.");
50
51 // Adjusts token balances of the two addresses
52 balances[msg.sender] -= amount;
53 balances[receiver] += amount;
54
55 // Emits the event defined earlier
56 emit Transfer(msg.sender, receiver, amount);
57 }
58}
सभी दिखाएँ
कॉपी करें

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

1pragma solidity ^0.5.10;
2
3// Imports symbols from other files into the current contract.
4// In this case, a series of helper contracts from OpenZeppelin.
5// Learn more: 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// The `is` keyword is used to inherit functions and keywords from external contracts.
13// In this case, `CryptoPizza` inherits from the `IERC721` and `ERC165` contracts.
14// Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance
15contract CryptoPizza is IERC721, ERC165 {
16 // Uses OpenZeppelin's SafeMath library to perform arithmetic operations safely.
17 // Learn more: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath
18 using SafeMath for uint256;
19
20 // Constant state variables in Solidity are similar to other languages
21 // but you must assign from an expression which is constant at compile time.
22 // Learn more: 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 // Struct types let you define your own type
28 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs
29 struct Pizza {
30 string name;
31 uint256 dna;
32 }
33
34 // Creates an empty array of Pizza structs
35 Pizza[] public pizzas;
36
37 // Mapping from pizza ID to its owner's address
38 mapping(uint256 => address) public pizzaToOwner;
39
40 // Mapping from owner's address to number of owned token
41 mapping(address => uint256) public ownerPizzaCount;
42
43 // Mapping from token ID to approved address
44 mapping(uint256 => address) pizzaApprovals;
45
46 // You can nest mappings, this example maps owner to operator approvals
47 mapping(address => mapping(address => bool)) private operatorApprovals;
48
49 // Internal function to create a random Pizza from string (name) and DNA
50 function _createPizza(string memory _name, uint256 _dna)
51 // The `internal` keyword means this function is only visible
52 // within this contract and contracts that derive this contract
53 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters
54 internal
55 // `isUnique` is a function modifier that checks if the pizza already exists
56 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers
57 isUnique(_name, _dna)
58 {
59 // Adds Pizza to array of Pizzas and get id
60 uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1);
61
62 // Checks that Pizza owner is the same as current user
63 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions
64
65 // note that address(0) is the zero address,
66 // indicating that pizza[id] is not yet allocated to a particular user.
67
68 assert(pizzaToOwner[id] == address(0));
69
70 // Maps the Pizza to the owner
71 pizzaToOwner[id] = msg.sender;
72 ownerPizzaCount[msg.sender] = SafeMath.add(
73 ownerPizzaCount[msg.sender],
74 1
75 );
76 }
77
78 // Creates a random Pizza from string (name)
79 function createRandomPizza(string memory _name) public {
80 uint256 randDna = generateRandomDna(_name, msg.sender);
81 _createPizza(_name, randDna);
82 }
83
84 // Generates random DNA from string (name) and address of the owner (creator)
85 function generateRandomDna(string memory _str, address _owner)
86 public
87 // Functions marked as `pure` promise not to read from or modify the state
88 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions
89 pure
90 returns (uint256)
91 {
92 // Generates random uint from string (name) + address (owner)
93 uint256 rand = uint256(keccak256(abi.encodePacked(_str))) +
94 uint256(_owner);
95 rand = rand % dnaModulus;
96 return rand;
97 }
98
99 // Returns array of Pizzas found by owner
100 function getPizzasByOwner(address _owner)
101 public
102 // Functions marked as `view` promise not to modify state
103 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions
104 view
105 returns (uint256[] memory)
106 {
107 // Uses the `memory` storage location to store values only for the
108 // lifecycle of this function call.
109 // Learn more: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack
110 uint256[] memory result = new uint256[](ownerPizzaCount[_owner]);
111 uint256 counter = 0;
112 for (uint256 i = 0; i < pizzas.length; i++) {
113 if (pizzaToOwner[i] == _owner) {
114 result[counter] = i;
115 counter++;
116 }
117 }
118 return result;
119 }
120
121 // Transfers Pizza and ownership to other address
122 function transferFrom(address _from, address _to, uint256 _pizzaId) public {
123 require(_from != address(0) && _to != address(0), "Invalid address.");
124 require(_exists(_pizzaId), "Pizza does not exist.");
125 require(_from != _to, "Cannot transfer to the same address.");
126 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
127
128 ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1);
129 ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1);
130 pizzaToOwner[_pizzaId] = _to;
131
132 // Emits event defined in the imported IERC721 contract
133 emit Transfer(_from, _to, _pizzaId);
134 _clearApproval(_to, _pizzaId);
135 }
136
137 /**
138 * Safely transfers the ownership of a given token ID to another address
139 * If the target address is a contract, it must implement `onERC721Received`,
140 * which is called upon a safe transfer, and return the magic value
141 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;
142 * otherwise, the transfer is reverted.
143 */
144 function safeTransferFrom(address from, address to, uint256 pizzaId)
145 public
146 {
147 // solium-disable-next-line arg-overflow
148 this.safeTransferFrom(from, to, pizzaId, "");
149 }
150
151 /**
152 * Safely transfers the ownership of a given token ID to another address
153 * If the target address is a contract, it must implement `onERC721Received`,
154 * which is called upon a safe transfer, and return the magic value
155 * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`;
156 * otherwise, the transfer is reverted.
157 */
158 function safeTransferFrom(
159 address from,
160 address to,
161 uint256 pizzaId,
162 bytes memory _data
163 ) public {
164 this.transferFrom(from, to, pizzaId);
165 require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implement onERC721Received.");
166 }
167
168 /**
169 * Internal function to invoke `onERC721Received` on a target address
170 * The call is not executed if the target address is not a contract
171 */
172 function _checkOnERC721Received(
173 address from,
174 address to,
175 uint256 pizzaId,
176 bytes memory _data
177 ) internal returns (bool) {
178 if (!isContract(to)) {
179 return true;
180 }
181
182 bytes4 retval = IERC721Receiver(to).onERC721Received(
183 msg.sender,
184 from,
185 pizzaId,
186 _data
187 );
188 return (retval == _ERC721_RECEIVED);
189 }
190
191 // Burns a Pizza - destroys Token completely
192 // The `external` function modifier means this function is
193 // part of the contract interface and other contracts can call it
194 function burn(uint256 _pizzaId) external {
195 require(msg.sender != address(0), "Invalid address.");
196 require(_exists(_pizzaId), "Pizza does not exist.");
197 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
198
199 ownerPizzaCount[msg.sender] = SafeMath.sub(
200 ownerPizzaCount[msg.sender],
201 1
202 );
203 pizzaToOwner[_pizzaId] = address(0);
204 }
205
206 // Returns count of Pizzas by address
207 function balanceOf(address _owner) public view returns (uint256 _balance) {
208 return ownerPizzaCount[_owner];
209 }
210
211 // Returns owner of the Pizza found by id
212 function ownerOf(uint256 _pizzaId) public view returns (address _owner) {
213 address owner = pizzaToOwner[_pizzaId];
214 require(owner != address(0), "Invalid Pizza ID.");
215 return owner;
216 }
217
218 // Approves other address to transfer ownership of Pizza
219 function approve(address _to, uint256 _pizzaId) public {
220 require(msg.sender == pizzaToOwner[_pizzaId], "Must be the Pizza owner.");
221 pizzaApprovals[_pizzaId] = _to;
222 emit Approval(msg.sender, _to, _pizzaId);
223 }
224
225 // Returns approved address for specific Pizza
226 function getApproved(uint256 _pizzaId)
227 public
228 view
229 returns (address operator)
230 {
231 require(_exists(_pizzaId), "Pizza does not exist.");
232 return pizzaApprovals[_pizzaId];
233 }
234
235 /**
236 * Private function to clear current approval of a given token ID
237 * Reverts if the given address is not indeed the owner of the token
238 */
239 function _clearApproval(address owner, uint256 _pizzaId) private {
240 require(pizzaToOwner[_pizzaId] == owner, "Must be pizza owner.");
241 require(_exists(_pizzaId), "Pizza does not exist.");
242 if (pizzaApprovals[_pizzaId] != address(0)) {
243 pizzaApprovals[_pizzaId] = address(0);
244 }
245 }
246
247 /*
248 * Sets or unsets the approval of a given operator
249 * An operator is allowed to transfer all tokens of the sender on their behalf
250 */
251 function setApprovalForAll(address to, bool approved) public {
252 require(to != msg.sender, "Cannot approve own address");
253 operatorApprovals[msg.sender][to] = approved;
254 emit ApprovalForAll(msg.sender, to, approved);
255 }
256
257 // Tells whether an operator is approved by a given owner
258 function isApprovedForAll(address owner, address operator)
259 public
260 view
261 returns (bool)
262 {
263 return operatorApprovals[owner][operator];
264 }
265
266 // Takes ownership of Pizza - only for approved users
267 function takeOwnership(uint256 _pizzaId) public {
268 require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved.");
269 address owner = this.ownerOf(_pizzaId);
270 this.transferFrom(owner, msg.sender, _pizzaId);
271 }
272
273 // Checks if Pizza exists
274 function _exists(uint256 pizzaId) internal view returns (bool) {
275 address owner = pizzaToOwner[pizzaId];
276 return owner != address(0);
277 }
278
279 // Checks if address is owner or is approved to transfer Pizza
280 function _isApprovedOrOwner(address spender, uint256 pizzaId)
281 internal
282 view
283 returns (bool)
284 {
285 address owner = pizzaToOwner[pizzaId];
286 // Disable solium check because of
287 // https://github.com/duaraghav8/Solium/issues/175
288 // solium-disable-next-line operator-whitespace
289 return (spender == owner ||
290 this.getApproved(pizzaId) == spender ||
291 this.isApprovedForAll(owner, spender));
292 }
293
294 // Check if Pizza is unique and doesn't exist yet
295 modifier isUnique(string memory _name, uint256 _dna) {
296 bool result = true;
297 for (uint256 i = 0; i < pizzas.length; i++) {
298 if (
299 keccak256(abi.encodePacked(pizzas[i].name)) ==
300 keccak256(abi.encodePacked(_name)) &&
301 pizzas[i].dna == _dna
302 ) {
303 result = false;
304 }
305 }
306 require(result, "Pizza with such name already exists.");
307 _;
308 }
309
310 // Returns whether the target address is a contract
311 function isContract(address account) internal view returns (bool) {
312 uint256 size;
313 // Currently there is no better way to check if there is a contract in an address
314 // than to check the size of the code at that address.
315 // See https://ethereum.stackexchange.com/a/14016/36603
316 // for more details about how this works.
317 // TODO Check this again before the Serenity release, because all addresses will be
318 // contracts then.
319 // solium-disable-next-line security/no-inline-assembly
320 assembly {
321 size := extcodesize(account)
322 }
323 return size > 0;
324 }
325}
सभी दिखाएँ
कॉपी करें

अग्रिम पठन

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

  • स्मार्ट अनुबंध
  • एथेरियम वर्चुअल मशीन
  • अनुबंध आकार सीमा से लड़ने के लिए अनुबंधों को छोटा करना – आपके स्मार्ट अनुबंध के आकार को कम करने के लिए कुछ व्यावहारिक सुझाव।
  • इवेंट्स के साथ स्मार्ट अनुबंधों से डेटा लॉगिंग – स्मार्ट अनुबंध इवेंट्स का परिचय और आप डेटा लॉग करने के लिए उनका उपयोग कैसे कर सकते हैं।
  • Solidity से अन्य अनुबंधों के साथ इंटरैक्ट करें – मौजूदा अनुबंध से स्मार्ट अनुबंध कैसे परिनियोजित करें और इसके साथ इंटरैक्ट करें।

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