Hướng dẫn về Solidity: Giới thiệu về Lập trình Solidity cho Người mới bắt đầu

Hướng dẫn về Solidity

Solidity là một ngôn ngữ hướng đối tượng, cấp cao để phát triển dApps (Ứng dụng phi tập trung), trên chuỗi khối Ethereum.

Blockchain là một mạng ngang hàng của các máy tính, được gọi là các nút, chia sẻ tất cả dữ liệu và mã trong mạng.

Vì vậy, nếu bạn là một thiết bị được kết nối với chuỗi khối, bạn là một nút trong mạng và bạn nói chuyện với tất cả các nút máy tính khác trong mạng (chúng tôi sẽ nói cách thiết lập nút Ethereum trên máy cục bộ của bạn trong các hướng dẫn sau).

Bây giờ bạn có một bản sao của tất cả dữ liệu và mã trên blockchain. Không cần máy chủ trung tâm nữa.

Ethereum là gì?

Nói một cách đơn giản nhất, Ethereum là một nền tảng phần mềm mở dựa trên công nghệ blockchain cho phép các nhà phát triển xây dựng và triển khai các ứng dụng phi tập trung.

Trong khi blockchain Bitcoin được sử dụng để theo dõi quyền sở hữu tiền kỹ thuật số (bitcoin), thì blockchain Ethereum tập trung vào việc chạy mã của các ứng dụng phi tập trung.

Trong chuỗi khối Ethereum, thay vì khai thác bitcoin, các thợ đào làm việc để kiếm Ether, một loại mã thông báo tiền điện tử cung cấp năng lượng cho mạng. Ngoài một loại tiền điện tử có thể giao dịch, Ether còn được các nhà phát triển ứng dụng sử dụng để thanh toán phí giao dịch và dịch vụ trên mạng Ethereum.

Có một loại mã thông báo thứ hai được sử dụng để trả phí cho thợ đào bao gồm các giao dịch trong khối của họ, nó được gọi là khí và mỗi lần thực hiện hợp đồng thông minh đều yêu cầu một lượng khí nhất định được gửi cùng với nó để lôi kéo thợ đào đặt nó vào chuỗi khối.

Bắt đầu với những điều cơ bản

Mã của Solidity được gói gọn trong các hợp đồng.

Chuỗi khối Ethereum cho phép chúng tôi thực thi mã với Máy ảo Ethereum (EVM) trên chuỗi khối với một thứ gọi là hợp đồng thông minh.

Hợp đồng thông minh là nơi tất cả logic kinh doanh của ứng dụng của chúng ta tồn tại – tất cả các biến và chức năng đều thuộc về một hợp đồng và đây sẽ là điểm khởi đầu của tất cả các dự án của bạn.

Danh bạ thông minh được viết bằng ngôn ngữ lập trình có tên là Solidity, trông giống như sự kết hợp giữa Javascript và C.

Phối lại IDE

Remix là công cụ trực tuyến cho phép bạn viết các hợp đồng thông minh Solidity, sau đó triển khai chúng và chạy nó.

Chỉ cần đi đến https://remix.ethereum.org từ trình duyệt của bạn và chúng tôi có thể bắt đầu viết mã.

Như bạn thấy, bạn có thể chọn giữa Solidity và Vyper. Cả hai đều là ngôn ngữ để viết các hợp đồng thông minh, Vyper giống python và Solidity giống javascript.

Cả hai đều có thể biên dịch sang mã bytecode EVM, giống như Javascript và Typescript. Chúng tôi đang chọn Solidity.

Ở phía bên trái có trình khám phá tệp. Theo mặc định, có hai tệp .sol, chỉ để demo cú pháp cơ bản (ballot.sol là hợp đồng thông minh, ballot_test.sol là tập lệnh để thử nghiệm hợp đồng thông minh đó).

Bạn chỉ cần nhấp vào nút dấu cộng đó và chúng tôi có thể bắt đầu mã hóa hợp đồng thông minh đầu tiên của mình.

Tất cả mã nguồn solidity phải bắt đầu bằng “phiên bản pragma” – phần khai báo về phiên bản của trình biên dịch Solidity mà mã này nên sử dụng. Điều này là để ngăn chặn sự cố với các phiên bản trình biên dịch trong tương lai có khả năng đưa ra các thay đổi có thể phá vỡ mã của bạn.

Nó trông như thế này:

độ rắn pragma ^ 0,4,25;

(đối với phiên bản Solidity trên 0.4.25)

hoặc là

sự vững chắc của pragma >= 0,5,0 < 0,6,0;

(đối với phiên bản Solidity từ 0.5.0 đến 0.6.0)

Sau đó, bạn tạo hợp đồng của mình bằng cách nhập từ dành riêng hợp đồng và tên tệp .sol của bạn (Điều quan trọng là tên hợp đồng khớp với tên của tệp, chúng ta sẽ thảo luận lý do sau). Trong trường hợp của chúng ta,

hợp đồng MyFirstContract {

}

Hãy biên dịch nó. Bạn chỉ cần điều hướng đến tab biên dịch đó ở bên trái và nhấp vào nút biên dịch lớn. Nếu có gì đó không ổn với mã, bạn sẽ thấy lỗi và cảnh báo ở đây (hãy từ bi với Solidity, nó vẫn là “ngôn ngữ trẻ”).

Với hợp đồng hiện tại của chúng tôi, mọi thứ đều ổn vì chúng tôi thực sự chưa làm được gì.

Bây giờ tôi sẽ cố tình tạo ra lỗi chỉ để cho bạn thấy một vài thứ. Bạn có thể chọn trình biên dịch theo cách thủ công từ menu thả xuống đó.

Hãy chọn phiên bản 0.4.26 chẳng hạn. Bây giờ, hãy biên dịch lại nó. Bây giờ bạn sẽ thấy lỗi “Trình biên dịch chưa được tải”.

Điều này là do chúng tôi đã chỉ định với pragma để hoạt động với các phiên bản trình biên dịch trên 0.5.0. Chỉ cần thay đổi lại phiên bản trình biên dịch và lỗi sẽ biến mất.

Được rồi, hãy viết mã ngay bây giờ!

Chúng ta sẽ bắt đầu với mã ‘Hello world’ đơn giản và các hàm lấy và đặt, chỉ để làm quen với cú pháp.

Hợp đồng theo nghĩa Solidity là một tập hợp mã (các chức năng của nó) và dữ liệu (trạng thái của nó) nằm tại một địa chỉ cụ thể trên chuỗi khối Ethereum.

Đầu tiên, hãy xác định biến trạng thái được gọi là message chẳng hạn và kiểu của nó sẽ là chuỗi.

Hàm get của chúng tôi sẽ trả về giá trị của thông báo biến của chúng tôi và hàm set sẽ gán một giá trị mới cho thông báo biến của chúng tôi.

Cách gõ các hàm?

Đầu tiên, từ dành riêng chức năng sau đó là tên của chức năng và tham số cụ thể và sau đó .

hàm myFunction () trả về (bool) {

trả về true;

}

Các chức năng có thể công cộng hoặc là riêng tư. Nếu một hàm là công khai, nó có thể được gọi bên ngoài hợp đồng. Nếu một hàm là private thì nó có một phạm vi giới hạn và chỉ có thể được gọi từ hợp đồng hiện tại của nó (từ một số hàm khác chẳng hạn).

Dưới đây là danh sách của tất cả các chỉ định hiển thị chức năng:

  • công cộng: hiển thị bên ngoài và bên trong (tạo một hàm getter cho các biến lưu trữ / trạng thái)
  • riêng tư: chỉ hiển thị trong hợp đồng hiện tại
  • bên ngoài: chỉ hiển thị bên ngoài (chỉ cho các chức năng) – tức là chỉ có thể được gọi là tin nhắn (qua this.func)
  • nội bộ: chỉ hiển thị trong nội bộ

Các chức năng có thể nguyên chất, lượt xem, hoặc là phải trả. Nếu một hàm không ghi bất kỳ dữ liệu nào trên blockchain thì rất nên xem, vì các hàm xem không tốn bất kỳ chi phí nào.

Dưới đây là danh sách tất cả các Công cụ sửa đổi hàm (cũng có các công cụ sửa đổi cho các biến trạng thái, sự kiện và đối số sự kiện nhưng sẽ nói về chúng sau):

  • nguyên chất: Không cho phép sửa đổi hoặc truy cập trạng thái.
  • lượt xem: Không cho phép sửa đổi trạng thái.
  • phải trả: Cho phép họ nhận Ether cùng với một cuộc gọi.

Nếu Hàm trả về giá trị nào đó, bạn cần chỉ định giá trị đó bằng từ dành riêng trả lại và sau đó trong dấu ngoặc thường để chỉ định kiểu nào hàm trả về. Trong trường hợp của chúng tôi, nó sẽ là chuỗi (vì chúng tôi trả về thông báo biến của chúng tôi là chuỗi)

Nếu Hàm không trả về bất kỳ giá trị nào, thì không cần trả lại tuyên bố.

Để truy cập một biến trạng thái, bạn không cần tiền tố điều này. như phổ biến trong các ngôn ngữ khác.

Do đó, một thực tế phổ biến là viết các đối số hàm với cú pháp gạch dưới (_thông điệp). Quy ước này đến từ Javascript, trong đó các phương thức và biến private bắt đầu bằng _.

Nói rõ hơn, mã của bạn sẽ hoạt động tốt và không có dấu gạch dưới, nhưng nó sẽ sạch hơn với chúng.

Bạn sẽ nhận thấy từ dành riêng ký ức trong mã của chúng tôi. Nếu bạn viết mã của chúng tôi mà không có bộ nhớ và đặt pragma thành một số phiên bản dưới 0,5. * Nó sẽ hoạt động tốt, nhưng khi bạn thay đổi trình biên dịch của mình thành trên 0,5. * EVM tạo ra lỗi biên dịch.

Lý do tại sao điều này xảy ra?

Chà, Máy ảo Ethereum có ba khu vực nơi nó có thể lưu trữ các vật phẩm.

  • Đầu tiên là lưu trữ, nơi tất cả các biến trạng thái hợp đồng cư trú. Mọi hợp đồng đều có bộ nhớ riêng và nó liên tục giữa các lần gọi hàm và khá tốn kém khi sử dụng.
  • Thứ hai là ký ức, điều này được sử dụng để giữ các giá trị tạm thời. Nó bị xóa giữa các lần gọi hàm (bên ngoài) và rẻ hơn khi sử dụng.
  • Cái thứ ba là cây rơm, được sử dụng để chứa các biến cục bộ nhỏ. Nó gần như miễn phí để sử dụng, nhưng chỉ có thể chứa một lượng giá trị hạn chế.

Đối với hầu hết tất cả các loại, bạn không thể chỉ định nơi chúng nên được lưu trữ, vì chúng được sao chép mỗi khi chúng được sử dụng.

Nhưng khi bạn làm việc với mảng hoặc cấu trúc và từ các phiên bản mới nhất cũng có chuỗi, trình biên dịch sẽ buộc bạn chỉ định khu vực lưu trữ.

Vì vậy, mã của chúng tôi bây giờ trông giống như sau:

độ rắn pragma ^ 0,5,0;

hợp đồng MyFirstContract {

thông điệp chuỗi;

function get () public view trả về (string memory) {

trả lại tin nhắn;

}

bộ hàm (bộ nhớ chuỗi _message) public {

tin nhắn = _message;

}

}

Xin lưu ý rằng một số nhà phát triển Solidity chia các chỉ số khả năng hiển thị đó thành các dòng riêng biệt để làm cho mã sạch hơn. Vì vậy, hàm get của chúng ta có thể được viết như thế này:

hàm get ()

công cộng

lượt xem

trả về (chuỗi)

{

trả lại tin nhắn;

}

Cách bạn chọn viết các hàm của mình thực sự tùy thuộc vào bạn.

Hãy soạn hợp đồng của chúng ta ngay bây giờ và kiểm tra nó.

Để biên dịch nó chỉ cần lặp lại các bước từ bên dưới (Biên dịch .sol nút hoặc cmd / ctrl + S từ bàn phím và nó sẽ tự động biên dịch lại)

Để thực sự xem nó hoạt động như thế nào (nếu việc biên dịch không tạo ra lỗi), bạn cần phải Triển khai hợp đồng của mình.

Để làm điều đó, hãy điều hướng đến tab Triển khai từ bên trái, đối với môi trường, hãy chọn JavaScriptVM và nhấn nút Triển khai.

Sau khi triển khai, bây giờ chúng ta có thể thấy các phương thức từ hợp đồng của mình. Bây giờ chúng ta hãy tập trung vào phần đó của màn hình.

Bạn có thể thấy rằng có hai nút (lấy & thiết lập) cho hai chức năng công cộng của chúng tôi. Nếu bất kỳ cái nào trong số đó là riêng tư, chúng tôi sẽ không thấy nó ở đây.

Nếu chúng ta nhấp vào nút nhận, EVM sẽ thực hiện chức năng nhận của chúng tôi.

Hãy xem nó hoạt động như thế nào.

Chúng tôi có một chuỗi trống. Không lớn, không khủng khiếp. Nhưng tại sao? Bởi vì chúng tôi đã không khởi tạo biến thông báo của mình ngay từ đầu.

Chỉ cần một lần tạm dừng nhanh chóng. Tôi muốn bạn giới thiệu với Remix Terminal. Nó nằm trong trình chỉnh sửa mã và tại đây bạn có thể theo dõi tất cả các giao dịch của mình, để xem liệu chúng có được thực hiện thành công hay không, gỡ lỗi chúng, xem chi tiết (băm giao dịch, v.v.) và hơn thế nữa.

Hiện tại, chúng tôi có hai giao dịch thành công. Một là Triển khai hợp đồng và chúng tôi phải trả chi phí ether (nhưng đừng lo, chúng tôi đang trong trình chỉnh sửa bây giờ mọi thứ đều là ảo) và thứ hai là Cuộc gọi của chúng tôi lượt xem chức năng.

Được rồi, hãy quay lại ngay bây giờ. Điều gì sẽ xảy ra nếu bây giờ chúng ta gọi hàm set?

Chúng ta cần truyền một đối số _message (ví dụ: “Hello World”) và nhấn nút giao dịch để thực thi chức năng. Bạn có thể theo dõi thành công của giao dịch trong Terminal.

Bây giờ chúng ta hãy gọi lại chức năng. Bây giờ nó trả về tin nhắn của chúng tôi.

Hãy thực hiện một số cải tiến cho mã của chúng tôi. Chúng tôi đã không khởi tạo thông báo thay đổi của mình. Làm thôi nào.

hợp đồng MyFirstContract {

chuỗi tin nhắn = "Chào thế giới!";

function get () public view trả về (string memory) {

trả lại tin nhắn;

}

bộ hàm (bộ nhớ chuỗi _message) public {

tin nhắn = _message;

}

}

Lưu ý rằng thông báo bây giờ là “Hello world!” Và khi chúng tôi gọi hàm get lần đầu tiên, nó sẽ không trả về chuỗi trống.

Để kiểm tra điều này, chúng tôi cần biên dịch hợp đồng của mình (cmd / ctrl + S).

Sau đó, để triển khai nó một lần nữa. Chúng tôi cần tạo một phiên bản hợp đồng mới (vì những thay đổi mà chúng tôi đã thực hiện) và xuất bản nó trên blockchain.

Chỉ cần xóa phiên bản trước khỏi trình chỉnh sửa (tất nhiên không phải từ chuỗi khối ảo của chúng tôi) và nhấn lại vào nút Triển khai. Hãy gọi chức năng nhận của chúng tôi ngay bây giờ.

Đẹp! Hãy đặt chức năng cuộc gọi ngay bây giờ.

Và nhận lại.

Mát mẻ.

Bây giờ hãy làm cho thông điệp của chúng ta trở thành không thay đổi.

Mã của chúng tôi bây giờ:

độ rắn pragma ^ 0,5,0;

hợp đồng MyFirstContract {

thông báo hằng chuỗi = "Chào thế giới!";

function get () public view trả về (string memory) {

trả lại tin nhắn;

}

bộ hàm (bộ nhớ chuỗi _message) public {

tin nhắn = _message;

}

}

Khi chúng tôi cố gắng biên dịch nó, chúng tôi gặp lỗi trong hàm thiết lập của mình. Đó là bởi vì người ta không thể thay đổi giá trị của một hằng số.

Chúng tôi sẽ loại bỏ hằng số đó ngay bây giờ.

Để khởi tạo các biến như thế này không phải là một lỗi, nhưng sẽ tốt hơn nhiều nếu chúng ta thực hiện điều đó trong hàm tạo. Bạn có thể viết hàm tạo trong Solidity với:

constructor () public {

// làm việc gì đó…

}

Constructor chỉ là một hàm khác đang được gọi trong quá trình triển khai hợp đồng thông minh. Mã của chúng tôi trông hơi khác một chút, nhưng nó hoạt động giống nhau.

độ rắn pragma ^ 0,5,0;

hợp đồng MyFirstContract {

thông điệp chuỗi;

constructor () public {

tin nhắn = "Chào thế giới!";

}

function get () public view trả về (string memory) {

trả lại tin nhắn;

}

bộ hàm (bộ nhớ chuỗi _message) public {

tin nhắn = _message;

}

}

Bạn có thể biên dịch lại và kiểm tra nếu muốn.

Cuối cùng, người ta có thể thay đổi khả năng hiển thị của các biến trạng thái. Nếu bạn thực hiện các biến trạng thái của mình công cộng điều đó có nghĩa là một người có thể yêu cầu các giá trị của họ từ bên ngoài hợp đồng.

Solidity sẽ tạo cho mỗi biến trạng thái công khai một phương thức có cùng tên có thể được gọi như một hàm thông thường (giống như hàm getter).

Điều này có nghĩa là chúng ta có thể loại bỏ hàm get, chỉ cần khai báo thông báo biến là công cộng, và mã của chúng tôi sẽ hoạt động giống nhau, nó sẽ sạch hơn nhiều và chúng tôi sẽ tốn ít chi phí hơn để triển khai nó vào Mạng chính một ngày.

Mã càng lớn, càng cần nhiều gas để thực thi nó và chi phí chạy dApp của chúng tôi sẽ tăng lên.

Khi chúng tôi phát triển các hợp đồng thông minh, chúng tôi cần phải:

  • Có hiệu quả – tỷ lệ khí tiêu thụ cần thấp
  • tóm lược – một khi bạn triển khai hợp đồng thông minh, nó không thể thay đổi được và nó được công khai 24/24, mọi dòng mã (hãy tưởng tượng một hacker tìm thấy lỗi và có thể khai thác dApp của bạn)

Mã cuối cùng của chúng tôi cho ngày hôm nay trông giống như sau:

độ rắn pragma ^ 0,5,0;

hợp đồng MyFirstContract {

chuỗi thông báo công khai;

constructor () public {

tin nhắn = "Chào thế giới!";

}

bộ hàm (bộ nhớ chuỗi _message) public {

tin nhắn = _message;

}

}

Hãy triển khai nó và kiểm tra nó.

Bạn có thể thấy nút thông báo đó. Nó đang được tạo vì thông báo biến trạng thái của chúng tôi là công khai.

Nếu chúng ta gọi như vậy, nó sẽ trả về cho chúng ta một giá trị đang được khởi tạo thông qua hàm tạo (đó là “Hello world!”).

Đẹp. Hãy thử nghiệm bộ chức năng bây giờ.

Cách học Solidity?

Bản thân Solidity là một ngôn ngữ khá đơn giản, nhưng để trở thành một nhà phát triển Solidity giỏi, người ta cần hiểu cách mọi thứ hoạt động trên Ethereum.

  • Solidity là ngôn ngữ lập trình cấp cao với cú pháp tương tự như ECMAScript (javascript).
  • Nó biên dịch thành mã bytecode EVM, điều mà chỉ EVM mới có thể hiểu được.
  • Trình biên dịch được gọi là Solc.

Hãy lấy hợp đồng đơn giản này làm ví dụ:

độ rắn pragma ^ 0,5,0;

hợp đồng Ví dụ {

uint a = 10 + 5;

}

Đơn giản như thế. Bây giờ chúng ta hãy biên dịch nó. Nếu chúng ta vào Chi tiết hợp đồng trong Terminal, chúng ta có thể thấy rất nhiều thông tin.

Trong trường hợp này, mã đã biên dịch là:

0x6080604052600f600055348015601457600080fd5b5060358060226000396000f3fe6080604052600080fdfea165627a7a72305820bf75c57b7d8745a79baee513ead21a9eb8b075896c8916e4c591

Các giá trị dài này là đại diện hệ thập lục phân của hợp đồng cuối cùng, còn được gọi là mã bytecode. EVM chỉ hiểu được bytecode.

Tuy nhiên, nếu có sự cố xảy ra, chúng tôi gặp phải một số lỗi chẳng hạn như không thể gỡ lỗi bytecode.

Opcodes

Ngôn ngữ trên bytecode là opcode. Opcode là ngôn ngữ lập trình cấp thấp. Solidity và Opcode giống như C và Assembly Language chẳng hạn.

Vì vậy, khi chúng tôi cần gỡ lỗi một số giao dịch không thành công, chúng tôi gỡ lỗi opcode.

Một điều bạn nên biết về Solidity và gỡ lỗi – nó rất khó. Nhưng không phải là không thể, vì vậy chúng ta hãy đi sâu vào nó.

Đây là opcode của hợp đồng mẫu của chúng tôi:

0 PUSH1 60

02 PUSH1 40

04 THÊM

05 PUSH1 0f

07 PUSH1 00

09 CỬA HÀNG

10 CALLVALUE

11 DUP1

12 ISZERO

13 PUSH1 14

15 JUMPI

16 PUSH1 00

18 DUP1

19 LẠI

20 JUMPDEST

21 POP

22 PUSH1 35

24 DUP1

25 PUSH1 22

27 PUSH1 00

29 MÃ SỐ

30 PUSH1 00

32 QUAY LẠI

33 KHÔNG HỢP LỆ

34 PUSH1 80

36 PUSH1 40

38 THÊM

39 PUSH1 00

41 DUP1

42 REVERT

43 KHÔNG HỢP LỆ

44 LOG1

45 PUSH6 627a7a723058

52 SHA3

53 KHÔNG HỢP LỆ

54 PUSH22 c57b7d8745a79baee513ead21a9eb8b075896f8e4c59

77 KHÔNG HỢP LỆ

78 DUP10

79 VÀ

80 JUMPI

81 KHÔNG HỢP LỆ

82 CÂN BẰNG

83 PUSH29 750029

Opcodes là các hướng dẫn cấp thấp mà con người có thể đọc được của chương trình. Tất cả các mã opcode đều có bản sao thập lục phân, ví dụ: THÊM0x52.

EVM là Máy xếp chồng. Nó dựa trên cấu trúc LIFO (Last In First Out). Để đơn giản hóa, hãy tưởng tượng việc xếp các lát bánh mì trong lò vi sóng, lát CUỐI CÙNG bạn cho vào là lát ĐẦU TIÊN bạn lấy ra.

Trong số học thông thường, chúng tôi viết phương trình của chúng tôi theo cách này:

10 + 2 * 2

và Câu trả lời là 14, bởi vì chúng ta thực hiện phép nhân trước khi cộng.

Trong một máy xếp chồng, nó hoạt động theo nguyên tắc LIFO:

2 2 * 10 +

Có nghĩa là, đặt 2 vào ngăn xếp trước, tiếp theo là 2 khác, sau đó là hành động nhân. Kết quả là 4 người ngồi trên cùng của ngăn xếp. Bây giờ thêm số 10 vào đầu 4 và cuối cùng cộng 2 số lại với nhau. Giá trị cuối cùng của ngăn xếp trở thành 14.

Hành động đưa dữ liệu vào ngăn xếp được gọi là lệnh PUSH và hành động xóa dữ liệu khỏi ngăn xếp được gọi là lệnh POP. Rõ ràng là opcode phổ biến nhất mà chúng ta thấy trong ví dụ ở trên là PUSH1 có nghĩa là đưa 1 byte dữ liệu vào ngăn xếp.

Vì vậy, hướng dẫn này:

PUSH1 0x60

nghĩa là đặt giá trị 1 byte là “0x60” trong ngăn xếp. Thật trùng hợp, giá trị thập lục phân cho PUSH1 cũng xảy ra là “0x60”. Loại bỏ “0x” không bắt buộc, chúng tôi có thể viết logic này trong bytecode là “6060”.

Hãy để chúng tôi đi xa hơn một chút.

PUSH1 0x60 PUSH1 0x40 THÊM

MSTORE (0x52) nhận 2 đầu vào và không tạo ra đầu ra. Các mã opcodes trên có nghĩa là:

PUSH1 (0x60): đặt 0x60 vào ngăn xếp.

PUSH1 (0x40): đặt 0x40 vào ngăn xếp.

THÊM (0x52): phân bổ không gian bộ nhớ 0x60 và di chuyển đến vị trí 0x40.

Bytecode kết quả là:

6060604052

Trên thực tế, chúng tôi luôn nhìn thấy con số kỳ diệu “6060604052” này ở đầu bất kỳ mã byte vững chắc nào bởi vì nó cách hợp đồng thông minh khởi động.

Để làm phức tạp thêm vấn đề, 0x40 hoặc 0x60 không thể được hiểu là số thực 40 hoặc 60. Vì chúng là số thập lục phân nên 40 thực sự tương đương với 64 (16¹ x 4) và 60 tương đương với 96 (16¹ x 6) trong hệ thập phân.

Tóm lại, những gì “PUSH1 0x60 PUSH1 0x40 MSTORE” đang làm là phân bổ 96 byte bộ nhớ và di chuyển con trỏ đến đầu byte thứ 64. Bây giờ chúng ta có 64 byte cho không gian đầu và 32 byte cho bộ nhớ tạm thời.

Trong EVM, có 3 nơi để lưu trữ dữ liệu. Thứ nhất, trong ngăn xếp. Chúng tôi vừa sử dụng mã opcode PUSH để lưu trữ dữ liệu ở đó theo ví dụ trên.

Thứ hai là trong bộ nhớ (RAM), nơi chúng tôi sử dụng opcode MSTORE và cuối cùng, trong bộ nhớ đĩa, nơi chúng tôi sử dụng SSTORE để lưu trữ dữ liệu. Khí cần thiết để lưu trữ dữ liệu vào bộ nhớ là đắt nhất và lưu trữ dữ liệu để xếp chồng là rẻ nhất.

Bây giờ, đã đến lúc quay lại mã Solidity của chúng tôi từ hướng dẫn này và tóm tắt lại những gì chúng tôi đã học về từ dành riêng ký ức và cách trình biên dịch buộc chúng tôi chỉ định cách chúng tôi lưu trữ các chuỗi, ví dụ:.

Chúng tôi chỉ đề cập đến những điều cơ bản về bytecode và một số opcodes.

Chúng tôi không cần biết mã opcodes để bắt đầu viết hợp đồng thông minh!

Mặt khác, việc xử lý lỗi EVM vẫn còn rất sơ khai và rất tiện lợi để xem các mã quang khi có sự cố.

Phần kết luận

Bài học đầu tiên này có lý thuyết nhiều hơn một chút so với mã hóa thực tế, nhưng điều rất quan trọng đối với người mới bắt đầu là phải biết cách mọi thứ hoạt động trên Ethereum. Trong các hướng dẫn tiếp theo, chúng tôi sẽ viết một số mã thú vị hơn và tìm hiểu cách triển khai mã thông báo của riêng chúng tôi trên chuỗi khối Ethereum.

Cho đến lúc đó &# 128075;