Bỏ qua để đến nội dung

Cơ bản về Solidity

Solidity là ngôn ngữ tiêu chuẩn công nghiệp để xây dựng các ứng dụng Web3 phi tập trung trên máy ảo tương thích với EVM của TRON. Tài liệu này giới thiệu các khái niệm Hợp đồng thông minh cốt lõi, từ biến trạng thái, ánh xạ (mappings) cho đến tính bất biến và thực thi nguyên tử, được thiết kế đặc biệt cho các nhà phát triển bước vào hệ sinh thái TRON.

Nếu bạn mới làm quen với việc phát triển blockchain, bạn có thể thắc mắc: Solidity có phải là ngôn ngữ Hợp đồng thông minh duy nhất không?

Không, nó không phải là duy nhất. Bạn có thể nghe nói về Rust (dùng trên Solana), Vyper (giống Python cho EVM), hoặc Move (dùng trên Aptos/Sui). Tuy nhiên, Solidity là tiêu chuẩn công nghiệp không thể tranh cãi.

Học Solidity là kỹ năng mang lại đòn bẩy cao nhất trong Web3. Bởi vì phần lớn các blockchain—bao gồm TRON, Ethereum, Polygon, Binance Smart Chain và Avalanche—sử dụng môi trường tương thích với EVM, việc viết Solidity cho phép mã nguồn của bạn chạy trên hầu hết mọi mạng lưới lớn.

Nếu bạn đang chọn một ngôn ngữ để bắt đầu hành trình phát triển blockchain của mình, Solidity chắc chắn là nơi tốt nhất để bắt đầu.


Bức tranh toàn cảnh: Cách Web2 gặp gỡ Web3

Phần tiêu đề “Bức tranh toàn cảnh: Cách Web2 gặp gỡ Web3”

Trước khi đi sâu vào code, sẽ hữu ích nếu bạn hiểu về kiến trúc. Một ứng dụng web thực sự giao tiếp với một Hợp đồng thông minh như thế nào?

  1. Hợp đồng thông minh (Backend): Bạn viết logic bằng Solidity. Sau khi được biên dịch và triển khai, nó tồn tại vĩnh viễn trên blockchain TRON.
  2. ABI (Cây cầu): Khi bạn biên dịch Solidity, nó tạo ra một Giao diện Nhị phân Ứng dụng (ABI). Đây đơn giản là một tệp JSON cho frontend JavaScript của bạn biết những hàm nào tồn tại trong hợp đồng và cách định dạng dữ liệu cho chúng.
  3. Ví (Danh tính & Bảo mật): Người dùng cài đặt một tiện ích mở rộng trình duyệt như Ví TronLink. Nó chứa private key của họ và ký các giao dịch một cách an toàn mà không tiết lộ bí mật của họ cho frontend của bạn.
  4. TronWeb (API): Frontend của bạn sử dụng thư viện JavaScript tronweb để yêu cầu ví ký một giao dịch, sau đó nó được phát lên Mạng lưới TRON để kích hoạt các hàm Solidity của bạn.

(Nếu bạn muốn đi sâu hơn vào khía cạnh JavaScript sau này, hãy đánh dấu trang Hướng dẫn tronweb SDK của chúng tôi.)


Solidity có cú pháp rất giống với JavaScript, C++ và Python, và nó là một ngôn ngữ có kiểu tĩnh (bạn phải định nghĩa kiểu dữ liệu của mọi biến). Tuy nhiên, môi trường mà nó chạy trong đó khiến nó trở nên khác biệt về cơ bản.

Nếu bạn đến từ Web2, đây là những khoảnh khắc “Aha!” sẽ thay đổi cách bạn suy nghĩ về lập trình:

Khi bạn triển khai một tập lệnh Python lên máy chủ, bạn luôn có thể SSH vào và sửa lỗi. Trong Solidity, một khi hợp đồng đã được triển khai, nó không thể thay đổi. Nếu có lỗi, nó là vĩnh viễn. (Các nhà phát triển sử dụng các “proxy patterns” nâng cao để nâng cấp hợp đồng, nhưng bản triển khai gốc là bất biến).

Trong JavaScript, bạn tạo mảng và đối tượng mà không cần đắn đo suy nghĩ. Trong Solidity, ghi dữ liệu vào bộ nhớ vĩnh viễn của blockchain tốn tài nguyên mạng. Trên TRON, điều này tiêu thụ Năng lượng. Các nhà phát triển dành nhiều thời gian để tối ưu hóa các kiểu dữ liệu nhằm tiết kiệm tiền cho người dùng. (Tò mò về cách Năng lượng hoạt động? Xem Hướng dẫn Mô hình phí của chúng tôi.)

3. Việc thực thi sẽ Roll Back khi Thất bại

Phần tiêu đề “3. Việc thực thi sẽ Roll Back khi Thất bại”

Nếu một tập lệnh Python gặp lỗi ở giữa quá trình cập nhật cơ sở dữ liệu, bạn có thể nhận được dữ liệu được cập nhật một phần. Trong Solidity, các thay đổi trạng thái là nguyên tử (atomic). Nếu một hàm gặp lỗi hoặc một câu lệnh require() thất bại, toàn bộ giao dịch sẽ bị hoàn tác. Giống như chưa từng có chuyện gì xảy ra, mặc dù người dùng vẫn trả Phí mạng cho việc thực thi không thành công.

Các blockchain phải hoàn toàn mang tính tất định (mọi node phải tính toán ra cùng một kết quả chính xác). Bởi vì toán học dấu phẩy động (0.1 + 0.2 = 0.30000000000000004) có thể thay đổi một chút giữa các kiến trúc CPU khác nhau, Solidity không hỗ trợ số thập phân.

Để biểu diễn 1.5 TRX, bạn biểu diễn nó bằng một số nguyên khổng lồ sử dụng đơn vị nhỏ nhất của nó (SUN): 1500000. Đừng lo lắng về việc thực hiện phép toán này một cách thủ công—frontend của bạn sẽ đơn giản sử dụng tronWeb.toSun(1.5)tronWeb.fromSun(1500000) để xử lý các chuyển đổi cho người dùng.


Dưới đây là những khối xây dựng cơ bản bạn sẽ sử dụng khi viết Hợp đồng thông minh trên TRON.

1. Biến trạng thái & Thuộc tính toàn cục

Phần tiêu đề “1. Biến trạng thái & Thuộc tính toàn cục”

Các biến trạng thái được lưu trữ vĩnh viễn trên blockchain. Solidity cũng cung cấp các “Biến toàn cục” cung cấp cho bạn thông tin về blockchain và người gọi hợp đồng.

pragma solidity ^0.8.18;
contract TypesExample {
// Các biến trạng thái (Được lưu trữ vĩnh viễn trên blockchain TRON)
uint256 public myNumber = 42; // Số nguyên không dấu (không có số âm)
address public myAddress; // Địa chỉ TRON (bắt đầu bằng T)
bool public isActive = true; // Boolean
string public greeting = "Hello!"; // Văn bản
function getCallerInfo() public view returns (address, uint256) {
// Các biến toàn cục có sẵn trong mọi hàm
// msg.sender được chèn tự động bởi Ví TronLink của người dùng
address caller = msg.sender;
uint256 timestamp = block.timestamp; // Thời gian khối hiện tại
return (caller, timestamp);
}
}

Nếu bạn biết từ điển trong Python hoặc Đối tượng trong JavaScript, bạn sẽ biết Mappings. Chúng là cách hiệu quả nhất để lưu trữ dữ liệu dạng key-value trên blockchain.

pragma solidity ^0.8.18;
contract MappingExample {
// Một ánh xạ từ Địa chỉ TRON tới số dư uint256
mapping(address => uint256) public balances;
function addBalance() public {
// msg.sender là ví đang thực thi giao dịch
balances[msg.sender] += 100;
}
}

Các hàm là nơi chứa logic thực sự. Bạn có thể kiểm soát ai được phép gọi một hàm bằng cách sử dụng modifiers. Độc đáo nhất là, các hàm có thể được đánh dấu là payable, nghĩa là chúng có thể nhận TRX một cách an toàn trực tiếp bên trong giao dịch.

pragma solidity ^0.8.18;
contract FunctionsExample {
address public owner;
constructor() {
// Chạy một lần khi hợp đồng được triển khai
owner = msg.sender;
}
// Một modifier kiểm tra điều kiện trước khi hàm chạy
modifier onlyOwner() {
require(msg.sender == owner, "Chỉ chủ sở hữu mới có thể làm điều này!");
_; // Tiếp tục thực thi hàm
}
// Một hàm thay đổi trạng thái (tốn Năng lượng)
function changeOwner(address newOwner) public onlyOwner {
owner = newOwner;
}
// Từ khóa 'payable' cho phép hàm này nhận TRX
function deposit() public payable {
// msg.value tự động được điền với số lượng TRX (tính bằng SUN) được gửi bởi người dùng
require(msg.value > 0, "Phải gửi TRX!");
}
}

Hợp đồng thông minh không thể dễ dàng “nói chuyện” với thế giới bên ngoài. Thay vào đó, chúng phát ra các Sự kiện (Events). Một ứng dụng frontend (sử dụng tronweb) có thể lắng nghe các sự kiện này và cập nhật giao diện người dùng khi chúng xảy ra, đây là cách các dApp giữ đồng bộ theo thời gian thực.

pragma solidity ^0.8.18;
contract EventExample {
// Khai báo sự kiện
event DataUpdated(address indexed user, uint256 newValue);
function updateData(uint256 _value) public {
// ... thực hiện logic ...
// Phát sự kiện lên mạng lưới
emit DataUpdated(msg.sender, _value);
}
}

Các Mẫu Tiêu chuẩn (Không Cần Phát minh lại Bánh xe)

Phần tiêu đề “Các Mẫu Tiêu chuẩn (Không Cần Phát minh lại Bánh xe)”

Khi xây dựng phần mềm truyền thống, bạn sử dụng các gói và thư viện. Trong Web3, bảo mật là tối quan trọng, vì vậy các nhà phát triển dựa vào các hợp đồng tiêu chuẩn đã được kiểm toán.

Nếu bạn muốn xây dựng một token TRC-20, bạn không nên viết nó từ đầu. Bạn nhập code đã được kiểm toán từ các thư viện như OpenZeppelin. Bởi vì TVM tương thích với EVM, các hợp đồng Ethereum tiêu chuẩn của OpenZeppelin hoạt động hoàn hảo trên TRON. (Để tìm hiểu thêm về các cơ chế token đặc thù của TRON, hãy xem Hướng dẫn Tiêu chuẩn Token của chúng tôi.)


Solidity là một chủ đề rộng lớn, và trang này chỉ là phần khởi đầu. Khi bạn xây dựng các dApp TRON phức tạp hơn, bạn chắc chắn sẽ cần tìm kiếm các giải pháp, mẫu thiết kế và hướng dẫn trực tuyến.

Khi tìm kiếm trợ giúp, bạn không nhất thiết phải thêm từ “TRON” vào các truy vấn tìm kiếm của mình. Các tìm kiếm chung về Solidity hoạt động hoàn hảo. Hãy thử tìm kiếm:

  • “Solidity mappings vs arrays”
  • “OpenZeppelin ERC-20 tutorial” (Hãy nhớ, code ERC-20 giống hệt code TRC-20!)
  • “Solidity reentrancy guard example”
  • “Solidity interface and abstract contracts”

Một vài lưu ý về các Hướng dẫn Ethereum

Phần tiêu đề “Một vài lưu ý về các Hướng dẫn Ethereum”

Bạn sẽ thấy rằng 99% các hướng dẫn, diễn đàn và câu trả lời StackOverflow về Solidity mà bạn tìm thấy trên mạng được viết cho Ethereum. Điều này hoàn toàn không sao. Bạn có thể sao chép, dán và học hỏi trực tiếp từ mã nguồn Solidity của Ethereum.

Tuy nhiên, có một số khác biệt nhỏ trong cách TRON xử lý các vấn đề ở bên dưới (ví dụ: TRON sử dụng Năng lượng và Băng thông thay vì hệ thống Phí mạng thống nhất của Ethereum, và các khối TRON nhanh hơn).

Bây giờ bạn đã nắm được ngôn ngữ, hãy đánh dấu trang Tham khảo Nhanh của chúng tôi. Nó chứa tất cả các endpoint quan trọng của Mạng lưới TRON, chain ID và các đoạn mã khởi tạo bạn sẽ cần khi bắt đầu xây dựng dApp của mình!