Chuyển đến nội dung chính
Change page

Cấu trúc của hợp đồng thông minh

Một hợp đồng thông minh là một chương trình chạy tại một địa chỉ trên Ethereum. Chúng được tạo thành từ dữ liệu và các hàm có thể thực thi khi nhận được một giao dịch. Dưới đây là tổng quan về những gì tạo nên một hợp đồng thông minh.

Điều kiện tiên quyết

Đảm bảo rằng bạn đã đọc về hợp đồng thông minh trước. Tài liệu này giả định rằng bạn đã quen thuộc với các ngôn ngữ lập trình như JavaScript hoặc Python.

Dữ liệu

Bất kỳ dữ liệu hợp đồng nào cũng phải được gán cho một vị trí: hoặc là storage hoặc memory. Việc sửa đổi bộ nhớ lưu trữ trong một hợp đồng thông minh rất tốn kém, vì vậy bạn cần cân nhắc xem dữ liệu của mình nên nằm ở đâu.

Lưu trữ

Dữ liệu cố định được gọi là lưu trữ (storage) và được biểu diễn bằng các biến trạng thái. Những giá trị này được lưu trữ vĩnh viễn trên Chuỗi khối. Bạn cần khai báo kiểu dữ liệu để hợp đồng có thể theo dõi xem nó cần bao nhiêu dung lượng lưu trữ trên Chuỗi khối khi biên dịch.

// Ví dụ Solidity
contract SimpleStorage {
    uint storedData; // Biến trạng thái
    // ...
}
# Ví dụ Vyper
storedData: int128

Nếu bạn đã từng lập trình các ngôn ngữ hướng đối tượng, có thể bạn sẽ quen thuộc với hầu hết các kiểu dữ liệu. Tuy nhiên, address có thể sẽ mới mẻ đối với bạn nếu bạn mới làm quen với việc phát triển Ethereum.

Kiểu address có thể chứa một địa chỉ Ethereum tương đương với 20 byte hoặc 160 bit. Nó trả về dưới dạng ký hiệu thập lục phân với tiền tố 0x.

Các kiểu khác bao gồm:

  • boolean
  • số nguyên (integer)
  • số thực dấu phẩy tĩnh (fixed point numbers)
  • mảng byte kích thước cố định
  • mảng byte kích thước động
  • hằng số hữu tỉ và số nguyên
  • hằng chuỗi
  • hằng số thập lục phân
  • enums

Để có thêm giải thích, hãy xem tài liệu:

Bộ nhớ

Các giá trị chỉ được lưu trữ trong suốt thời gian thực thi hàm của hợp đồng được gọi là biến bộ nhớ (memory variables). Vì chúng không được lưu trữ vĩnh viễn trên Chuỗi khối, nên việc sử dụng chúng rẻ hơn rất nhiều.

Tìm hiểu thêm về cách EVM lưu trữ dữ liệu (Lưu trữ, Bộ nhớ và Ngăn xếp) trong tài liệu Solidity (opens in a new tab).

Biến môi trường

Ngoài các biến bạn định nghĩa trong hợp đồng của mình, còn có một số biến toàn cục đặc biệt. Chúng chủ yếu được sử dụng để cung cấp thông tin về Chuỗi khối hoặc giao dịch hiện tại.

Ví dụ:

Thuộc tínhBiến trạng tháiMô tả
block.timestampuint256Dấu thời gian kỷ nguyên của khối hiện tại
msg.senderaddressNgười gửi thông điệp (lời gọi hiện tại)

Các hàm

Nói một cách đơn giản nhất, các hàm có thể lấy thông tin hoặc thiết lập thông tin để phản hồi lại các giao dịch đến.

Có hai loại lời gọi hàm:

  • internal – chúng không tạo ra một lời gọi EVM
    • Các hàm nội bộ (internal) và biến trạng thái chỉ có thể được truy cập từ bên trong (nghĩa là từ bên trong hợp đồng hiện tại hoặc các hợp đồng kế thừa từ nó)
  • external – chúng tạo ra một lời gọi EVM
    • Các hàm bên ngoài (external) là một phần của giao diện hợp đồng, có nghĩa là chúng có thể được gọi từ các hợp đồng khác và thông qua các giao dịch. Một hàm bên ngoài f không thể được gọi từ bên trong (nghĩa là f() không hoạt động, nhưng this.f() thì có).

Chúng cũng có thể là public hoặc private

  • Các hàm public có thể được gọi từ bên trong hợp đồng hoặc từ bên ngoài thông qua các thông điệp
  • Các hàm private chỉ hiển thị đối với hợp đồng mà chúng được định nghĩa và không hiển thị trong các hợp đồng kế thừa

Cả hàm và biến trạng thái đều có thể được đặt là public (công khai) hoặc private (riêng tư)

Dưới đây là một hàm để cập nhật một biến trạng thái trên một hợp đồng:

// Ví dụ Solidity
function update_name(string value) public {
    dapp_name = value;
}
  • Tham số value có kiểu string được truyền vào hàm: update_name
  • Nó được khai báo là public, nghĩa là bất kỳ ai cũng có thể truy cập nó
  • Nó không được khai báo là view, vì vậy nó có thể sửa đổi trạng thái hợp đồng

Các hàm View

Những hàm này cam kết không sửa đổi trạng thái dữ liệu của hợp đồng. Các ví dụ phổ biến là các hàm "getter" – ví dụ: bạn có thể sử dụng hàm này để nhận số dư của người dùng.

// Ví dụ Solidity
function balanceOf(address _owner) public view returns (uint256 _balance) {
    return ownerPizzaCount[_owner];
}
dappName: public(string)

@view
@public
def readName() -> string:
  return dappName

Những gì được coi là sửa đổi trạng thái:

  1. Ghi vào các biến trạng thái.
  2. Phát ra các sự kiện (opens in a new tab).
  3. Tạo các hợp đồng khác (opens in a new tab).
  4. Sử dụng selfdestruct.
  5. Gửi ether thông qua các lời gọi.
  6. Gọi bất kỳ hàm nào không được đánh dấu là view hoặc pure.
  7. Sử dụng các lời gọi cấp thấp (low-level calls).
  8. Sử dụng inline assembly có chứa các opcode nhất định.

Các hàm khởi tạo

Các hàm constructor chỉ được thực thi một lần khi hợp đồng được triển khai lần đầu. Giống như constructor trong nhiều ngôn ngữ lập trình dựa trên lớp (class-based), các hàm này thường khởi tạo các biến trạng thái với các giá trị được chỉ định của chúng.

# Ví dụ Vyper

@external
def __init__(_beneficiary: address, _bidding_time: uint256):
    self.beneficiary = _beneficiary
    self.auctionStart = block.timestamp
    self.auctionEnd = self.auctionStart + _bidding_time

Các hàm tích hợp sẵn

Ngoài các biến và hàm bạn định nghĩa trong hợp đồng của mình, còn có một số hàm tích hợp sẵn đặc biệt. Ví dụ rõ ràng nhất là:

  • address.send() – Solidity
  • send(address) – Vyper

Chúng cho phép các hợp đồng gửi ETH đến các tài khoản khác.

Viết các hàm

Hàm của bạn cần:

  • biến tham số và kiểu dữ liệu (nếu nó chấp nhận tham số)
  • khai báo internal/external
  • khai báo pure/view/payable
  • kiểu trả về (nếu nó trả về một giá trị)

Một hợp đồng hoàn chỉnh có thể trông giống như thế này. Ở đây, hàm constructor cung cấp một giá trị ban đầu cho biến dapp_name.

Sự kiện và nhật ký

Các sự kiện cho phép hợp đồng thông minh của bạn giao tiếp với frontend hoặc các ứng dụng đăng ký theo dõi khác. Khi một giao dịch được xác thực và thêm vào một khối, các hợp đồng thông minh có thể phát ra các sự kiện và ghi lại thông tin vào nhật ký, sau đó frontend có thể xử lý và sử dụng thông tin này.

Các ví dụ có chú thích

Đây là một số ví dụ được viết bằng Solidity. Nếu bạn muốn thử nghiệm với mã nguồn, bạn có thể tương tác với chúng trong Remix (opens in a new tab).

Hello world

Token

Tài sản kỹ thuật số độc nhất

Đọc thêm

Hãy xem tài liệu của Solidity và Vyper để có cái nhìn tổng quan đầy đủ hơn về các hợp đồng thông minh: