Σχόλια
Μπορείτε να γράψετε σχόλια για να τεκμηριώσετε τον κώδικά σας. Σχόλια μονής γραμμής (//) και σχόλια πολλών γραμμών (/…/) είναι δυνατά.
// This is a single-line comment.
/*
This is a
multi-line comment.
*/
Αδεια
Δεδομένου ότι ο κώδικας έξυπνου συμβολαίου είναι πάντα ανοιχτός σε οποιονδήποτε, ο μεταγλωττιστής solidity ενθαρρύνει τη χρήση αναγνωριστικών αδειών αναγνώσιμων από μηχανή για την αποφυγή νομικών προβλημάτων. Κάθε αρχείο προέλευσης πρέπει να ξεκινά με ένα σχόλιο που να υποδεικνύει την άδεια χρήσης του:
// SPDX-License-Identifier: MIT
Έκδοση Pragma
Η λέξη-κλειδί pragma χρησιμοποιείται για την ενεργοποίηση συγκεκριμένων χαρακτηριστικών ή ελέγχων μεταγλωττιστή. Τα αρχεία προέλευσης μπορούν (και πρέπει) να σχολιάζονται με μια έκδοση pragma για την απόρριψη της μεταγλώττισης με μελλοντικές εκδόσεις μεταγλωττιστή που ενδέχεται να εισάγουν μη συμβατές αλλαγές.
pragma solidity ^0.8.2;
Εισαγωγές
Οι δηλώσεις εισαγωγής στερεότητας επιτρέπουν την εισαγωγή κώδικα από άλλο αρχείο. Αυτό σας βοηθά να σπάσετε το έργο σας σε αρθρωτό κώδικα σε πολλά μικρότερα αρχεία.
// global imports => import "filename";
import “Math.sol”
// named imports => import * as symbolName from "filename";
import * as formula from “Math.sol”
Μεταβλητές κατάστασης
Οι μεταβλητές κατάστασης είναι μεταβλητές των οποίων οι τιμές αποθηκεύονται μόνιμα σε συμβατική αποθήκευση.
contract SimpleStorage {
uint storedData1; // Unsinged integer; can be negative
int storedData2; // Signed integer; cannot be negative
bool storedData3, // Boolean value (true or false)
address storedData4; // 20 byte ethereum address
//complex data types
int[] storedData5; // a dynamic array of int
int[3] storedData6; // a fixed array of 3 int
string storedData7; // a literal string eg "Hello"
}
Κατασκευές
Οι δομές είναι προσαρμοσμένοι τύποι που μπορούν να ομαδοποιήσουν πολλές μεταβλητές
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
contract Ballot {
// Struct
struct Voter {
uint weight;
bool voted;
address delegate;
uint vote;
}
}
Αριθμοί
Τα enums μπορούν να χρησιμοποιηθούν για τη δημιουργία προσαρμοσμένων τύπων με ένα πεπερασμένο σύνολο «σταθερών τιμών»
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
contract Purchase {
enum State { Created, Locked, Inactive } // Enum
}
Μεταβλητή ορατότητα
Η ορατότητα μιας μεταβλητής υπαγορεύει από πού στον κώδικα είναι δυνατή η πρόσβαση σε μια μεταβλητή. Υπάρχουν 3 πιθανές ορατότητες: ιδιωτική, εσωτερική (προεπιλογή) και δημόσια.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
contract SimpleStorage {
// Visible only inside contract
private uint storedData1;
// Visible inside the contract and derived contracts (Default)
internal int storedData2;
// Like internal, but getter functions are automatically generated
public bool storedData3,
}
Λειτουργίες
Οι συναρτήσεις είναι οι εκτελέσιμες μονάδες κώδικα. Οι λειτουργίες ορίζονται συνήθως μέσα σε ένα συμβόλαιο, αλλά μπορούν επίσης να οριστούν και εκτός συμβάσεων.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
contract SimpleAuction {
function bid() public payable { // Function
// ...
}
}
// Helper function defined outside of a contract
function helper(uint x) pure returns (uint) {
return x * 2;
}
Τροποποιητές συνάρτησης
Οι τροποποιητές μπορούν να χρησιμοποιηθούν για να αλλάξουν τη συμπεριφορά των συναρτήσεων με δηλωτικό τρόπο. Για παράδειγμα, μπορείτε να χρησιμοποιήσετε έναν τροποποιητή για να διασφαλίσετε αυτόματα ότι μόνο οι πωλητές μπορούν να καταχωρήσουν ένα NFT για δημοπρασία.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
contract Purchase {
address public seller;
modifier onlySeller() { // Modifier
require(
msg.sender == seller,
"Only seller can call this."
);
_;
}
function list() public view onlySeller { // Modifier usage
// ...
}
}
Εσωτερικές κλήσεις λειτουργιών
Οι συναρτήσεις του τρέχοντος συμβολαίου μπορούν να καλούνται απευθείας („εσωτερικά“), επίσης αναδρομικά, όπως φαίνεται σε αυτό το παράλογο παράδειγμα:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.9.0;
// This will report a warning
contract C {
function g(uint a) public pure returns (uint ret) { return a + f(); }
function f() internal pure returns (uint ret) { return g(7) + f(); }
}
Κλήσεις εξωτερικών λειτουργιών
Οι συναρτήσεις μπορούν επίσης να κληθούν χρησιμοποιώντας το this.g(8);
και c.g(2);
σημειογραφία, όπου c
είναι περίπτωση συμβολαίου και g
είναι μια συνάρτηση που ανήκει σε c
.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2 <0.9.0;
contract InfoFeed {
function info() public payable returns (uint ret) { return 42; }
}
contract Consumer {
InfoFeed feed;
function setFeed(InfoFeed addr) public { feed = addr; }
function callFeed() public { feed.info{value: 10, gas: 800}(); }
}
Ονομασμένες κλήσεις και παράμετροι ανώνυμης συνάρτησης
Τα ορίσματα κλήσης συναρτήσεων μπορούν να δοθούν ονομαστικά, με οποιαδήποτε σειρά, εάν περικλείονται { }
όπως φαίνεται στο παρακάτω παράδειγμα.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
contract C {
mapping(uint => uint) data;
function f() public {
set({value: 2, key: 3});
}
function set(uint key, uint value) public {
data[key] = value;
}
}
Εκδηλώσεις
Η εκδήλωση είναι ένα κληρονομικό μέλος μιας σύμβασης. Εκπέμπεται ένα συμβάν, αποθηκεύει τα ορίσματα που διαβιβάζονται στα αρχεία καταγραφής συναλλαγών. Τα συμβάντα είναι τρόποι επικοινωνίας με μια εφαρμογή πελάτη ή έναν ιστότοπο διεπαφής ότι κάτι έχει συμβεί στο blockchain.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
contract SimpleAuction {
event HighestBidIncreased(address bidder, uint amount); // Event
function bid() public payable {
// ...
emit HighestBidIncreased(msg.sender, msg.value); // Triggering event
}
}
Σφάλματα
Τα σφάλματα σάς επιτρέπουν να ορίσετε περιγραφικά ονόματα και δεδομένα για καταστάσεις αποτυχίας. Μπορείτε να χρησιμοποιήσετε το NatSpec για να περιγράψετε το σφάλμα στον χρήστη. Μπορούν να οριστούν εντός και εκτός των συμβολαίων.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
/// Not enough funds for transfer. Requested `requested`,
/// but only `available` available.
error NotEnoughFunds(uint requested, uint available);
contract Token {
mapping(address => uint) balances;
function transfer(address to, uint amount) public {
uint balance = balances[msg.sender];
if (balance < amount)
revert NotEnoughFunds(amount, balance);
// ...
}
}
χειριστές
a+b // Addition
a-b // Subtraction
a*b // Multiplication
a/b // Division
a * (b + c) // grouping
person.age // member
person[age] // member
!(a == b) // logical not
a != b // not equal
a = b // assignment
a == b // equals
a != b // unequal
a === b // strict equal
a !== b // strict unequal
a < b a > b // less and greater than
a <= b a >= b // less or equal, greater or eq
a += b // a = a + b (works with - * %...)
a && b // logical and
a || b // logical or
Ειδικές Μονάδες
Μονάδες Αιθέρα
Ένας κυριολεκτικός αριθμός μπορεί να πάρει ένα επίθημα wei, gwei ή αιθέρα για να καθορίσει μια υποονομασία του Ether, όπου οι αριθμοί Ether χωρίς postfix θεωρούνται Wei.
Μονάδες χρόνου
Επιθήματα όπως seconds
, minutes
, hours
, days
και weeks
μετά οι κυριολεκτικοί αριθμοί μπορούν να χρησιμοποιηθούν για τον καθορισμό μονάδων χρόνου όπου τα δευτερόλεπτα είναι η βασική μονάδα και οι μονάδες θεωρούνται αφελώς με τον ακόλουθο τρόπο: – 1 == 1 seconds
– 1 minutes == 60 seconds
– 1 hours == 60 minutes
– 1 days == 24 hours
– 1 weeks == 7 days
Καθολικές συναρτήσεις και μεταβλητές
Υπάρχουν ειδικές μεταβλητές και συναρτήσεις που υπάρχουν πάντα στον καθολικό χώρο ονομάτων
Ιδιότητες αποκλεισμού και συναλλαγής
blockhash(uint blockNumber) returns (bytes32)
: κατακερματισμός του δεδομένου μπλοκ ότανblocknumber
είναι ένα από τα 256 πιο πρόσφατα μπλοκ. διαφορετικά επιστρέφει μηδένblock.basefee
(uint
): βασική χρέωση τρέχοντος μπλοκ (EIP-3198 και EIP-1559)block.chainid
(uint
): αναγνωριστικό τρέχουσας αλυσίδαςblock.coinbase
(address payable
): η τρέχουσα διεύθυνση του εξορύκτη μπλοκblock.difficulty
(uint
): τρέχουσα δυσκολία μπλοκblock.gaslimit
(uint
): τρέχον όριο αερίου μπλοκblock.number
(uint
): τρέχων αριθμός μπλοκblock.timestamp
(uint
): η τρέχουσα χρονική σήμανση μπλοκ ως δευτερόλεπτα από την εποχή του unixgasleft() returns (uint256)
: υπολειπόμενο αέριοmsg.data
(bytes calldata
): πλήρη δεδομένα κλήσεωνmsg.sender
(address
): αποστολέας του μηνύματος (τρέχουσα κλήση)msg.sig
(bytes4
): τα πρώτα τέσσερα byte των δεδομένων κλήσης (δηλ. αναγνωριστικό συνάρτησης)msg.value
(uint
): αριθμός των wei που στάλθηκαν με το μήνυμαtx.gasprice
(uint
): τιμή φυσικού αερίου της συναλλαγήςtx.origin
(address
): αποστολέας της συναλλαγής (πλήρης αλυσίδα κλήσεων)
Λειτουργίες Κωδικοποίησης και Αποκωδικοποίησης ABI
abi.decode(bytes memory encodedData, (...)) returns (...)
: Το ABI-αποκωδικοποιεί τα δεδομένα, ενώ οι τύποι δίνονται σε παρένθεση ως δεύτερο όρισμα. Παράδειγμα:(uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))
abi.encode(...) returns (bytes memory)
: ABI-κωδικοποιεί τα δεδομένα ορίσματαabi.encodePacked(...) returns (bytes memory)
: Εκτελεί συσκευασμένη κωδικοποίηση των δεδομένων επιχειρημάτων. Σημειώστε ότι η συσκευασμένη κωδικοποίηση μπορεί να είναι διφορούμενη!abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)
: ABI-κωδικοποιεί τα δεδομένα ορίσματα ξεκινώντας από το δεύτερο και προτάσσει τον δεδομένο επιλογέα τεσσάρων byteabi.encodeWithSignature(string memory signature, ...) returns (bytes memory)
: Ισοδυναμεί μεabi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)
abi.encodeCall(function functionPointer, (...)) returns (bytes memory)
: ABI-κωδικοποιεί μια κλήση προςfunctionPointer
με τα επιχειρήματα που βρίσκονται στην πλειάδα. Πραγματοποιεί πλήρη έλεγχο τύπου, διασφαλίζοντας ότι οι τύποι ταιριάζουν με την υπογραφή της λειτουργίας. Το αποτέλεσμα είναι ίσοabi.encodeWithSelector(functionPointer.selector, (...))
Μαθηματικές και Κρυπτογραφικές Συναρτήσεις
addmod(uint x, uint y, uint k) returns (uint)
: υπολογισμός(x + y) % k
όπου η προσθήκη γίνεται με αυθαίρετη ακρίβεια και δεν τυλίγεται στο2**256
. Υποστηρίξτε ότιk != 0
ξεκινώντας από την έκδοση 0.5.0.mulmod(uint x, uint y, uint k) returns (uint)
: υπολογισμός(x * y) % k
όπου ο πολλαπλασιασμός εκτελείται με αυθαίρετη ακρίβεια και δεν τυλίγεται στο2**256
. Υποστηρίξτε ότιk != 0
ξεκινώντας από την έκδοση 0.5.0.keccak256(bytes memory) returns (bytes32)
: υπολογίστε τον κατακερματισμό Keccak-256 της εισόδουsha256(bytes memory) returns (bytes32)
: υπολογίστε τον κατακερματισμό SHA-256 της εισόδουripemd160(bytes memory) returns (bytes20)
: υπολογισμός κατακερματισμού RIPEMD-160 της εισόδουecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)
: ανάκτηση της διεύθυνσης που σχετίζεται με το δημόσιο κλειδί από την υπογραφή ελλειπτικής καμπύλης ή επιστροφή μηδέν στο σφάλμα. Οι παράμετροι συνάρτησης αντιστοιχούν στις τιμές ECDSA της υπογραφής:r
= πρώτα 32 byte υπογραφήςs
= δεύτερο 32 byte υπογραφήςv
= τελικό 1 byte υπογραφήςecrecover
επιστρέφει έναaddress
και όχι έναaddress payable
. Βλέπω πληρωτέα διεύθυνση για μετατροπή, σε περίπτωση που χρειαστεί να μεταφέρετε χρήματα στη διεύθυνση που ανακτήθηκε.
Λειτουργίες χειρισμού σφαλμάτων
assert(bool condition)
προκαλεί ένα σφάλμα πανικού και συνεπώς την επαναφορά της αλλαγής κατάστασης εάν δεν πληρούται η συνθήκη – για χρήση για εσωτερικά σφάλματα.require(bool condition)
επιστρέφει εάν δεν πληρούται η συνθήκη – για χρήση για σφάλματα σε εισόδους ή εξωτερικά εξαρτήματα.require(bool condition, string memory message)
επιστρέφει εάν δεν πληρούται η συνθήκη – για χρήση για σφάλματα σε εισόδους ή εξωτερικά εξαρτήματα. Παρέχει επίσης ένα μήνυμα σφάλματος.revert()
ματαιώσει την εκτέλεση και επαναφέρει τις αλλαγές κατάστασηςrevert(string memory reason)
ματαιώσει την εκτέλεση και επαναφέρει τις αλλαγές κατάστασης, παρέχοντας μια επεξηγηματική συμβολοσειρά
Τροποποιητές Λέξεις-κλειδιά
pure
για λειτουργίες: Δεν επιτρέπει την τροποποίηση ή την πρόσβαση της κατάστασης.view
για συναρτήσεις: Δεν επιτρέπει την τροποποίηση της κατάστασης.payable
για λειτουργίες: Τους επιτρέπει να λαμβάνουν Ether μαζί με μια κλήση.constant
για μεταβλητές κατάστασης: Δεν επιτρέπει την εκχώρηση (εκτός από την προετοιμασία), δεν καταλαμβάνει υποδοχή αποθήκευσης.immutable
για μεταβλητές κατάστασης: Επιτρέπει ακριβώς μία ανάθεση κατά το χρόνο κατασκευής και είναι σταθερή μετά. Αποθηκεύεται σε κώδικα.anonymous
για συμβάντα: Δεν αποθηκεύει την υπογραφή συμβάντος ως θέμα.indexed
για παραμέτρους συμβάντος: Αποθηκεύει την παράμετρο ως θέμα.virtual
για συναρτήσεις και τροποποιητές: Επιτρέπει την αλλαγή της συμπεριφοράς της συνάρτησης ή του τροποποιητή σε παράγωγα συμβόλαια.override
: Δηλώνει ότι αυτή η συνάρτηση, ο τροποποιητής ή η μεταβλητή δημόσιας κατάστασης αλλάζει τη συμπεριφορά μιας συνάρτησης ή τροποποιητή σε ένα βασικό συμβόλαιο.