Προτάσεις ασφάλειας συμβολαίων Ethereum

blog 1ΕιδήσειςΑναπτυσσόμενοιΕξέτασηΕπεξήγηση BlockchainΕκδηλώσεις και ΣυνέδριαΠατήστεΕνημερωτικά δελτία

Contents

Εγγραφείτε στο newsletter μας.

Διεύθυνση ηλεκτρονικού ταχυδρομείου

Σεβόμαστε το απόρρητό σας

HomeBlogBlockchain Ανάπτυξη

Προτάσεις ασφάλειας συμβολαίων Ethereum

Από τον τρόπο χειρισμού εξωτερικών κλήσεων σε προγράμματα δέσμευσης, ακολουθούν 10+ έξυπνα πρότυπα ασφάλειας συμβολαίων που πρέπει να ακολουθήσετε όταν χτίζετε στο Ethereum. Από ConsenSys 10 Ιουλίου 2020 Δημοσιεύτηκε στις 10 Ιουλίου 2020

Προτάσεις ασφάλειας συμβολαίων Ethereum

Όπως καλύψαμε στο Smart Contract Security Mindset, ένας προσεκτικός προγραμματιστής Ethereum διατηρεί πάντα πέντε βασικές αρχές:

  • Προετοιμαστείτε για αποτυχία
  • Ξεκινήστε προσεκτικά
  • Κρατήστε τις συμβάσεις απλές
  • Μείνετε ενημερωμένοι
  • Λάβετε υπόψη τις ιδιοσυγκρασίες του EVM

Σε αυτήν την ανάρτηση, θα βυθίσουμε τις ιδιοσυγκρασίες της EVM και θα ακολουθήσουμε μια λίστα προτύπων που πρέπει να ακολουθήσετε κατά την ανάπτυξη οποιουδήποτε έξυπνου συστήματος συμβάσεων στο Ethereum. Αυτό το κομμάτι προορίζεται κυρίως για ενδιάμεσους προγραμματιστές Ethereum. Εάν είστε ακόμα στα πρώτα στάδια της εξερεύνησης, ρίξτε μια ματιά στο πρόγραμμα προγραμματιστών blockchain της Ακαδημίας ConsenSys Academy. 

Εντάξει, ας βουτήξουμε.

Εξωτερικές κλήσεις

Να είστε προσεκτικοί όταν πραγματοποιείτε εξωτερικές κλήσεις

Οι κλήσεις σε μη αξιόπιστα έξυπνα συμβόλαια μπορούν να δημιουργήσουν πολλούς απροσδόκητους κινδύνους ή σφάλματα. Οι εξωτερικές κλήσεις ενδέχεται να εκτελούν κακόβουλο κώδικα σε αυτό το συμβόλαιο ή οποιοδήποτε άλλο συμβόλαιο από το οποίο εξαρτάται. Επομένως, αντιμετωπίστε κάθε εξωτερική κλήση ως πιθανό κίνδυνο ασφάλειας. Όταν δεν είναι δυνατό ή ανεπιθύμητο να αφαιρέσετε εξωτερικές κλήσεις, χρησιμοποιήστε τις συστάσεις στην υπόλοιπη ενότητα για να ελαχιστοποιήσετε τον κίνδυνο.

Επισήμανση μη αξιόπιστων συμβάσεων

Όταν αλληλεπιδράτε με εξωτερικές συμβάσεις, ονομάστε τις μεταβλητές σας, τις μεθόδους και τις διεπαφές συμβολαίου με τρόπο που καθιστά σαφές ότι η αλληλεπίδραση με αυτές είναι δυνητικά μη ασφαλής. Αυτό ισχύει για τις δικές σας λειτουργίες που καλούν εξωτερικά συμβόλαια.

// bad Bank.withdraw (100); // Δεν είναι σαφές εάν η αξιόπιστη ή μη αξιόπιστη συνάρτηση makeWithdrawal (ποσό δεν είναι) {// Δεν είναι σαφές ότι αυτή η συνάρτηση είναι δυνητικά μη ασφαλής Bank.withdraw (ποσό); } // καλή UntrustedBank.withdraw (100); // μη αξιόπιστη εξωτερική κλήση TrustedBank.withdraw (100); // εξωτερικό, αλλά αξιόπιστο τραπεζικό συμβόλαιο, το οποίο διατηρείται από τη συνάρτηση XYZ Corp makeUntrustedWithdrawal (ποσά) {UntrustedBank.withdraw (ποσό); } Γλώσσα κώδικα: PHP (php)

Αποφύγετε αλλαγές κατάστασης μετά από εξωτερικές κλήσεις

Είτε χρησιμοποιείτε ακατέργαστες κλήσεις (της φόρμας someAddress.call ()) ή κλήσεις συμβάσεων (της φόρμας ExternalContract.someMethod ()), υποθέστε ότι ενδέχεται να εκτελεστεί κακόβουλος κώδικας. Ακόμα κι αν το ExternalContract δεν είναι κακόβουλο, ο κακόβουλος κώδικας μπορεί να εκτελεστεί με οποιαδήποτε συμβόλαια καλεί.

Ένας ιδιαίτερος κίνδυνος είναι ο κακόβουλος κώδικας να παραβιάσει τη ροή ελέγχου, οδηγώντας σε ευπάθειες λόγω επανεισόδου. (Βλέπω Επανεισδοχή για πληρέστερη συζήτηση αυτού του προβλήματος).

Εάν πραγματοποιείτε μια κλήση σε ένα μη αξιόπιστο εξωτερικό συμβόλαιο, αποφύγετε αλλαγές κατάστασης μετά την κλήση. Αυτό το μοτίβο ονομάζεται επίσης μερικές φορές το ελέγχει-εφέ-αλληλεπιδράσεις μοτίβο.

Βλέπω SWC-107

Μην χρησιμοποιείτε μεταφορά () ή αποστολή ().

.μεταφορά () και. αποστολή () προωθήστε ακριβώς 2.300 αέριο στον παραλήπτη. Ο στόχος αυτού του επιδόματος φυσικού αερίου ήταν να αποφευχθεί ευπάθειες επανεισδοχής, αλλά αυτό έχει νόημα μόνο με την υπόθεση ότι το κόστος του φυσικού αερίου είναι σταθερό. EIP 1884, που ήταν μέρος του σκληρού πιρουνιού της Κωνσταντινούπολης, αύξησε το κόστος φυσικού αερίου της λειτουργίας SLOAD. Αυτό προκάλεσε την εναλλακτική λειτουργία ενός συμβολαίου να κοστίζει πάνω από 2300 αέριο. Σας συνιστούμε να σταματήσετε να χρησιμοποιείτε. Μεταφορά () και. Αποστολή () και αντί να χρησιμοποιήσετε. Κλήση ().

// κακή σύμβαση Εύθραυστη {λειτουργία ανάληψη (ποσό uint256) εξωτερικό {// Αυτό προωθεί 2300 αέριο, το οποίο ενδέχεται να μην είναι αρκετό εάν ο παραλήπτης // είναι σύμβαση και το κόστος του φυσικού αερίου αλλάξει. msg.sender.transfer (ποσό); }} // καλή σύμβαση Διορθώθηκε {λειτουργία ανάληψη (ποσό uint256) εξωτερικό {// Αυτό προωθεί όλο το διαθέσιμο αέριο. Φροντίστε να ελέγξετε την τιμή επιστροφής! (bool επιτυχία,) = msg.sender.call.value (ποσό) (""); απαιτούν (επιτυχία, "Η μεταφορά απέτυχε."); }} Γλώσσα κώδικα: JavaScript (javascript)

Σημειώστε ότι το .call () δεν κάνει τίποτα για να μετριάσει τις επιθέσεις επανεισόδου, επομένως πρέπει να ληφθούν και άλλες προφυλάξεις. Για να αποφύγετε επανειλημμένες επιθέσεις, χρησιμοποιήστε το ελέγχει-εφέ-αλληλεπιδράσεις μοτίβο.

Χειριστείτε λάθη σε εξωτερικές κλήσεις

Το Solidity προσφέρει μεθόδους κλήσεων χαμηλού επιπέδου που λειτουργούν σε μη επεξεργασμένες διευθύνσεις: address.call (), address.callcode (), address.delegatecall () και address.send (). Αυτές οι μέθοδοι χαμηλού επιπέδου δεν ρίχνουν ποτέ εξαίρεση, αλλά θα επιστρέψουν ψευδείς εάν η κλήση συναντήσει εξαίρεση. Από την άλλη πλευρά, οι κλήσεις συμβολαίου (π.χ. ExternalContract.doSomething ()) θα μεταδώσουν αυτόματα ένα ρίξιμο (για παράδειγμα, το ExternalContract.doSomething () θα ρίξει επίσης εάν το doSomething () ρίξει).

Εάν επιλέξετε να χρησιμοποιήσετε τις μεθόδους κλήσεων χαμηλού επιπέδου, βεβαιωθείτε ότι χειρίζεστε την πιθανότητα αποτυχίας της κλήσης, ελέγχοντας την τιμή επιστροφής.

// bad someAddress.send (55); someAddress.call.value (55) (""); // αυτό είναι διπλά επικίνδυνο, καθώς θα προωθήσει όλο το υπόλοιπο αέριο και δεν ελέγχει για το αποτέλεσμα someAddress.call.value (100) (bytes4 (sha3 ("κατάθεση()"))) // εάν η κατάθεση ρίξει μια εξαίρεση, η πρώτη κλήση () θα επιστρέψει μόνο ψευδής και η συναλλαγή ΔΕΝ θα αντιστραφεί // καλή (επιτυχία bool,) = someAddress.call.value (55) (""); if (! success) {// χειριστείτε τον κωδικό αποτυχίας} ExternalContract (someAddress) .deposit.value (100) (); Γλώσσα κώδικα: JavaScript (javascript)

Βλέπω SWC-104

Προωθητική ώθηση για εξωτερικές κλήσεις

Οι εξωτερικές κλήσεις μπορεί να αποτύχουν κατά λάθος ή σκόπιμα. Για να ελαχιστοποιηθεί η ζημιά που προκαλείται από τέτοιες αστοχίες, είναι συχνά καλύτερο να απομονωθεί κάθε εξωτερική κλήση στη δική της συναλλαγή που μπορεί να ξεκινήσει από τον παραλήπτη της κλήσης. Αυτό ισχύει ιδιαίτερα για τις πληρωμές, όπου είναι καλύτερο να αφήσετε τους χρήστες να αποσύρουν χρήματα αντί να ωθούν αυτόματα χρήματα σε αυτούς. (Αυτό μειώνει επίσης την πιθανότητα προβλήματα με το όριο αερίου.) Αποφύγετε το συνδυασμό πολλαπλών αιθερικών μεταφορών σε μία μόνο συναλλαγή.

// κακή δημοπρασία συμβολαίου {address tertinggiBidder; uint υψηλότερη προσφορά; προσφορά λειτουργίας () πληρωτέα {απαιτείται (τιμή msg.value >= υψηλότερη προσφορά); if (tertinggiBidder! = διεύθυνση (0)) {(επιτυχία bool,) = tertinggiBidder.call.value (tertinggiBid) (""); απαιτούν (επιτυχία)? // εάν αυτή η κλήση αποτυγχάνει σταθερά, κανένας άλλος δεν μπορεί να υποβάλει προσφορά} tertinggiBidder = msg.sender; υψηλότερη τιμή = msg.value; }} // καλή δημοπρασία συμβολαίου {address بلندBidder; uint υψηλότερη προσφορά; χαρτογράφηση (διεύθυνση => uint) επιστροφές χρημάτων προσφορά λειτουργίας () πληρωτέο εξωτερικό {απαιτείται (τιμή msg.value >= υψηλότερη προσφορά); if (tertinggiBidder! = διεύθυνση (0)) {επιστροφές χρημάτων [υψηλότερη προσφορά] + = υψηλότερη προσφορά; // καταγράψτε την επιστροφή χρημάτων που μπορεί να αξιώσει αυτός ο χρήστης} tertinggiBidder = msg.sender; υψηλότερη τιμή = msg.value; } λειτουργία pullRefund () εξωτερικό {uint refund = επιστροφές χρημάτων [msg.sender]; επιστροφές χρημάτων [msg.sender] = 0; (bool επιτυχία,) = msg.sender.call.value (επιστροφή χρημάτων) (""); απαιτούν (επιτυχία)? }} Γλώσσα κώδικα: JavaScript (javascript)

Βλέπω SWC-128

Μην μεταβιβάζετε την κλήση σε μη αξιόπιστο κώδικα

Η συνάρτηση delegatecall καλεί λειτουργίες από άλλες συμβάσεις σαν να ανήκουν στη σύμβαση καλούντος. Έτσι ο καλούντος μπορεί να αλλάξει την κατάσταση της διεύθυνσης κλήσης. Αυτό μπορεί να είναι ανασφαλές. Ένα παράδειγμα παρακάτω δείχνει πώς η χρήση του delegatecall μπορεί να οδηγήσει στην καταστροφή της σύμβασης και την απώλεια του υπολοίπου της.

σύμβαση Destructor {function doWork () εξωτερικό {selfdestruct (0); }} σύμβαση εργαζομένου {function doWork (address _internalWorker) public {// unsafe _internalWorker.delegatecall (bytes4 (keccak256 ("δούλεψε()"))) }} Γλώσσα κώδικα: JavaScript (javascript)

Εάν το Worker.doWork () καλείται με τη διεύθυνση του αναπτυσσόμενου συμβολαίου Destructor ως επιχείρημα, η σύμβαση Worker θα καταστραφεί μόνη της. Αναθέστε την εκτέλεση μόνο σε αξιόπιστα συμβόλαια και ποτέ σε μια παρεχόμενη από τον χρήστη διεύθυνση.

Προειδοποίηση

Μην υποθέσετε ότι οι συμβάσεις δημιουργούνται με μηδενικό υπόλοιπο. Ένας εισβολέας μπορεί να στείλει αιθέρα στη διεύθυνση ενός συμβολαίου προτού δημιουργηθεί. Τα συμβόλαια δεν πρέπει να υποθέτουν ότι η αρχική του κατάσταση περιέχει μηδενικό υπόλοιπο. Βλέπω τεύχος 61 Για περισσότερες πληροφορίες.

Βλέπω SWC-112

Να θυμάστε ότι ο αιθέρας μπορεί να σταλεί αναγκαστικά σε έναν λογαριασμό

Προσοχή στην κωδικοποίηση ενός αμετάβλητου που ελέγχει αυστηρά το υπόλοιπο ενός συμβολαίου.

Ένας εισβολέας μπορεί να στείλει βίαια αιθέρα σε οποιονδήποτε λογαριασμό. Αυτό δεν μπορεί να αποφευχθεί (ούτε με μια λειτουργία εναλλαγής που κάνει επαναφορά ()).

Ο εισβολέας μπορεί να το κάνει αυτό δημιουργώντας ένα συμβόλαιο, χρηματοδοτώντας το με 1 wei και επικαλούμενο selfdestruct (korbanAddress). Κανένας κωδικός δεν επικαλέστηκε το korbanAddress, επομένως δεν μπορεί να αποφευχθεί. Αυτό ισχύει επίσης για την επιβράβευση που αποστέλλεται στη διεύθυνση του ανθρακωρύχου, η οποία μπορεί να είναι οποιαδήποτε αυθαίρετη διεύθυνση.

Επίσης, δεδομένου ότι οι διευθύνσεις συμβολαίου μπορούν να υπολογιστούν εκ των προτέρων, ο αιθέρας μπορεί να σταλεί σε μια διεύθυνση πριν από την ανάπτυξη της σύμβασης.

Βλέπω SWC-132

Να θυμάστε ότι τα δεδομένα της αλυσίδας είναι δημόσια

Πολλές αιτήσεις απαιτούν τα δεδομένα που υποβάλλονται να είναι ιδιωτικά μέχρι κάποια στιγμή για να λειτουργήσουν. Παιχνίδια (π.χ. ψαλίδι ροκ-χαρτιού σε αλυσίδα) και μηχανισμοί δημοπρασίας (π.χ. σφραγισμένη προσφορά Δημοπρασίες Vickrey) είναι δύο σημαντικές κατηγορίες παραδειγμάτων. Εάν δημιουργείτε μια εφαρμογή όπου το απόρρητο αποτελεί πρόβλημα, βεβαιωθείτε ότι αποφεύγετε να απαιτείται από τους χρήστες να δημοσιεύουν πληροφορίες πολύ νωρίς. Η καλύτερη στρατηγική είναι η χρήση σχέδια δέσμευσης με ξεχωριστές φάσεις: πρώτα δεσμεύστε χρησιμοποιώντας το κατακερματισμό των τιμών και σε μια μεταγενέστερη φάση αποκαλύπτοντας τις τιμές.

Παραδείγματα:

  • Στο ψαλίδι ροκ χαρτί, απαιτήστε από τους δύο παίκτες να υποβάλουν πρώτα ένα hash της προβλεπόμενης κίνησής τους και στη συνέχεια να απαιτήσουν και οι δύο παίκτες να υποβάλουν την κίνηση τους. εάν η υποβληθείσα κίνηση δεν ταιριάζει με το κατακερματισμό, πετάξτε το.
  • Σε μια δημοπρασία, ζητήστε από τους παίκτες να υποβάλουν κατακερματισμό της αξίας προσφοράς τους σε μια αρχική φάση (μαζί με μια κατάθεση μεγαλύτερη από την αξία προσφοράς τους) και, στη συνέχεια, να υποβάλουν την τιμή προσφοράς της δημοπρασίας στη δεύτερη φάση.
  • Κατά την ανάπτυξη μιας εφαρμογής που εξαρτάται από μια γεννήτρια τυχαίων αριθμών, η παραγγελία θα πρέπει πάντα να είναι (1) οι παίκτες υποβάλλουν κινήσεις, (2) τυχαίος αριθμός που δημιουργείται, (3) οι παίκτες πληρώνονται. Πολλοί άνθρωποι ερευνούν ενεργά τις γεννήτριες τυχαίων αριθμών. Οι τρέχουσες βέλτιστες λύσεις στην κατηγορία περιλαμβάνουν κεφαλίδες μπλοκ Bitcoin (επαληθεύτηκαν μέσω http://btcrelay.org), σχήματα κατακερματισμού-αποκάλυψης (δηλ. ένα μέρος δημιουργεί έναν αριθμό, δημοσιεύει το κατακερματισμό του για «δέσμευση» στην τιμή και στη συνέχεια αποκαλύπτει την τιμή αργότερα) και ΡΑΝΤΑΟ. Καθώς το Ethereum είναι ένα ντετερμινιστικό πρωτόκολλο, δεν μπορείτε να χρησιμοποιήσετε καμία μεταβλητή εντός του πρωτοκόλλου ως έναν απρόβλεπτο τυχαίο αριθμό. Επίσης να γνωρίζετε ότι οι ανθρακωρύχοι έχουν σε κάποιο βαθμό τον έλεγχο της τιμής block.blockhash ()*.

Προσέξτε την πιθανότητα ορισμένοι συμμετέχοντες να “πέσουν εκτός σύνδεσης” και να μην επιστρέψουν

Μην εξαρτάτε τις διαδικασίες επιστροφής χρημάτων ή αξιώσεων από ένα συγκεκριμένο μέρος που εκτελεί μια συγκεκριμένη ενέργεια χωρίς κανέναν άλλο τρόπο να αντλήσετε χρήματα. Για παράδειγμα, σε ένα παιχνίδι ροκ-χαρτί-ψαλίδι, ένα κοινό λάθος είναι να μην κάνετε πληρωμή έως ότου και οι δύο παίκτες υποβάλουν τις κινήσεις τους. Ωστόσο, ένας κακόβουλος παίκτης μπορεί να «θλίψει» τον άλλο απλά χωρίς να υποβάλει την κίνηση του – στην πραγματικότητα, εάν ένας παίκτης δει την αποκάλυψη της κίνησης του άλλου παίκτη και αποφασίσει ότι έχασε, δεν έχει κανένα λόγο να υποβάλει τη δική του κίνηση. Αυτό το ζήτημα μπορεί επίσης να προκύψει στο πλαίσιο του διακανονισμού κρατικών καναλιών. Όταν τέτοιες καταστάσεις είναι ένα ζήτημα, (1) παρέχει έναν τρόπο παράκαμψης των μη συμμετεχόντων συμμετεχόντων, ίσως μέσω ενός χρονικού ορίου και (2) εξετάστε το ενδεχόμενο να προσθέσετε ένα επιπλέον οικονομικό κίνητρο για τους συμμετέχοντες να υποβάλουν πληροφορίες σε όλες τις καταστάσεις στις οποίες είναι υποτίθεται ότι το κάνει.

Προσοχή στην άρνηση του πιο αρνητικού υπογεγραμμένου ακέραιου

Η σταθερότητα παρέχει διάφορους τύπους για εργασία με υπογεγραμμένους ακέραιους αριθμούς. Όπως και στις περισσότερες γλώσσες προγραμματισμού, στη Σταθερότητα, ένας υπογεγραμμένος ακέραιος αριθμός με bit N μπορεί να αντιπροσωπεύει τιμές από -2 ^ (N-1) έως 2 ^ (N-1) -1. Αυτό σημαίνει ότι δεν υπάρχει θετικό ισοδύναμο για το MIN_INT. Η άρνηση εφαρμόζεται ως εύρεση του συμπληρώματος των δύο ενός αριθμού, έτσι η άρνηση του πιο αρνητικού αριθμού θα έχει ως αποτέλεσμα τον ίδιο αριθμό. Αυτό ισχύει για όλους τους υπογεγραμμένους ακέραιους τύπους στο Solidity (int8, int16,…, int256).

Negation συμβολαίου {function negate8 (int8 _i) δημόσιες καθαρές αποδόσεις (int8) {return -_i; } λειτουργία negate16 (int16 _i) δημόσιες καθαρές επιστροφές (int16) {return -_i; } int8 δημόσιο a = negate8 (-128); // -128 int16 δημόσιο b = negate16 (-128); // 128 int16 δημόσιο c = negate16 (-32768); // -32768} Γλώσσα κώδικα: PHP (php)

Ένας τρόπος να το χειριστείτε είναι να ελέγξετε την τιμή μιας μεταβλητής πριν από την άρνηση και να ρίξετε εάν είναι ίση με το MIN_INT. Μια άλλη επιλογή είναι να βεβαιωθείτε ότι ο πιο αρνητικός αριθμός δεν θα επιτευχθεί ποτέ χρησιμοποιώντας έναν τύπο με μεγαλύτερη χωρητικότητα (π.χ. int32 αντί για int16).

Ένα παρόμοιο πρόβλημα με τους τύπους int παρουσιάζεται όταν το MIN_INT πολλαπλασιάζεται ή διαιρείται με -1.

Είναι ο κωδικός blockchain σας ασφαλής? 

Ελπίζουμε ότι αυτές οι προτάσεις ήταν χρήσιμες. Εάν εσείς και η ομάδα σας προετοιμάζεστε για έναρξη ή ακόμα και στην αρχή του κύκλου ζωής της ανάπτυξης και χρειάζεστε τα έξυπνα συμβόλαιά σας ελεγμένα, μη διστάσετε να επικοινωνήσετε με την ομάδα μηχανικών ασφαλείας μας στο ConsenSys Diligence. Είμαστε εδώ για να σας βοηθήσουμε να ξεκινήσετε και να διατηρήσετε τις εφαρμογές Ethereum με 100% εμπιστοσύνη. 

Κάντε κράτηση για έλεγχο ασφαλείας

Κλείστε μια κριτική 1 ημέρας με την ομάδα εμπειρογνωμόνων ασφαλείας blockchain. Κάντε κράτηση για τη δική σας σήμερα Ασφάλεια Έξυπνα συμβόλαιαΕνημερωτικό δελτίοΕγγραφείτε στο ενημερωτικό μας δελτίο για τις τελευταίες ειδήσεις Ethereum, εταιρικές λύσεις, πόρους προγραμματιστών και πολλά άλλα. Διεύθυνση ηλεκτρονικού ταχυδρομείου Αποκλειστικό περιεχόμενοΠώς να δημιουργήσετε ένα επιτυχημένο προϊόν BlockchainΔιαδικτυακό σεμινάριο

Πώς να δημιουργήσετε ένα επιτυχημένο προϊόν Blockchain

Πώς να ρυθμίσετε και να εκτελέσετε έναν κόμβο EthereumΔιαδικτυακό σεμινάριο

Πώς να ρυθμίσετε και να εκτελέσετε έναν κόμβο Ethereum

Πώς να φτιάξετε το δικό σας API EthereumΔιαδικτυακό σεμινάριο

Πώς να φτιάξετε το δικό σας API Ethereum

Πώς να δημιουργήσετε ένα κοινωνικό κουπόνιΔιαδικτυακό σεμινάριο

Πώς να δημιουργήσετε ένα κοινωνικό κουπόνι

Χρήση εργαλείων ασφαλείας στην ανάπτυξη έξυπνων συμβάσεωνΔιαδικτυακό σεμινάριο

Χρήση εργαλείων ασφαλείας στην ανάπτυξη έξυπνων συμβάσεων

Το μέλλον των ψηφιακών στοιχείων ενεργητικού και του DeFiΔιαδικτυακό σεμινάριο

Το μέλλον των οικονομικών: Ψηφιακά περιουσιακά στοιχεία και DeFi

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me
Like this post? Please share to your friends:
Adblock
detector
map