Máy ảo TRON (TVM) cung cấp một môi trường tương thích EVM hiệu suất cao để triển khai các Hợp đồng thông minh Solidity. Mặc dù chia sẻ phần lớn các công cụ với Ethereum, hướng dẫn này nhấn mạnh các hành vi cụ thể, quan trọng của TVM, bao gồm xử lý timestamp theo mili-giây và logic tự hủy (self-destruct) đã được cập nhật, để đảm bảo việc triển khai an toàn và tối ưu.
Theo lịch sử, opcode selfdestruct đã bị vô hiệu hóa trên TRON. Tuy nhiên, sau khi Đề xuất Quản trị TRON Số 106 được thông qua (Tháng 4 năm 2026), hành vi hiện nay đã căn chỉnh với Ethereum (EIP-6780) để cải thiện tính tương thích của TVM:
Một Hợp đồng sẽ chỉ bị xóa nếu selfdestruct được thực thi trong cùng một giao dịch (transaction) mà nó tạo ra Hợp đồng đó.
Nếu được thực thi trong bất kỳ giao dịch nào sau đó, chỉ có việc chuyển tài sản TRX diễn ra và mã Hợp đồng vẫn nằm trên mạng lưới.
Chi phí Năng lượng khi gọi selfdestruct đã được điều chỉnh thành 5000.
Lưu trữ Tạm thời (Transient Storage) và Sao chép Bộ nhớ
Hỗ trợ cho TSTORE, TLOAD (EIP-1153) và MCOPY (EIP-5656) đã được thêm vào TVM như một phần của bản nâng cấp GreatVoyage-v4.8.0 (Kant) (Tháng 6 năm 2025). Điều này đảm bảo các nhà phát triển có thể chuyển đổi các hợp đồng sử dụng các bản nâng cấp Cancun/Dencun của Ethereum mà không cần sửa đổi.
Các địa chỉ TRON có kích thước 21 byte ở dạng nội bộ (các địa chỉ Ethereum là 20 byte). Mã hóa ABI bổ sung khoảng trống (pad) thành 32 byte giống như trên EVM, do đó các lệnh gọi Hợp đồng được mã hóa bằng ABI hoạt động bình thường. Tuy nhiên, nếu bạn thực hiện việc thao tác byte thô trên các địa chỉ (ví dụ: trong assembly), hãy tính đến kích thước 21-byte này.
Trên Ethereum, block.coinbase là địa chỉ của thợ đào/người xác thực. Trên TVM, nó là địa chỉ của Siêu Đại diện (Super Representative) đã tạo ra khối hiện tại. Không sử dụng block.coinbase làm nguồn sinh số ngẫu nhiên — nó có thể dự đoán được và dễ bị SR thao túng.
Không có Sự tương đương về Địa chỉ CREATE với Ethereum
Opcode CREATE dẫn xuất một địa chỉ Hợp đồng trên TRON theo cách khác với Ethereum. Nếu bạn đang triển khai các Hợp đồng phụ thuộc vào các địa chỉ CREATE mang tính tất định được tính toán off-chain, hãy tính toán lại chúng theo mô hình dẫn xuất địa chỉ của TRON. CREATE2 với một salt rõ ràng hoạt động chính xác cho các địa chỉ mang tính tất định.
Trên Ethereum, address.transfer(amount) có hạn mức gas cố định là 2,300. Trên TVM, lệnh gọi này tiêu thụ Năng lượng. Các mẫu thiết kế Reentrancy vốn dựa vào giới hạn gas 2,300 để đảm bảo an toàn có thể hoạt động khác biệt. Hãy sử dụng mẫu thiết kế checks-effects-interactions bất kể trường hợp nào.
TronBox hỗ trợ Solidity lên đến phiên bản 0.8.x. Sử dụng pragma ^0.8.0 hoặc ghim vào một phiên bản cụ thể. Solidity 0.8 bao gồm các kiểm tra chống tràn (overflow) tích hợp sẵn, qua đó loại bỏ sự cần thiết của SafeMath.
version.sol
// Task: Chỉ định phiên bản trình biên dịch Solidity cho TVM.
TRC-20 có chức năng giống hệt như ERC-20. Toàn bộ tài liệu tham khảo về chữ ký hàm, định nghĩa Sự kiện và các địa chỉ Hợp đồng mainnet đã biết đều có trong Tiêu chuẩn Token. Dưới đây là một TRC-20 hoàn chỉnh, tối giản, có thể triển khai kèm theo các ghi chú dành riêng cho TVM ở bên trong code.
SimpleTRC20.sol
// Task: Đoạn mã này định nghĩa một Hợp đồng token TRC-20 tối giản.
// SPDX-License-Identifier: MIT
pragmasolidity^0.8.18;
/**
* @title SimpleTRC20
* @dev Token TRC-20 tối giản có thể triển khai trên TRON.
6,// số thập phân (6 khớp với quy ước USDT trên TRON)
1_000_000// tổng cung khởi tạo
);
};
Một Hợp đồng ERC-20 OpenZeppelin tiêu chuẩn cũng sẽ triển khai một cách chính xác trên TRON dưới dạng TRC-20. Chỉ cần xem xét lại hai thứ trước khi triển khai: mỗi phép so sánh block.timestamp (nhân ngưỡng với 1000) và cách bạn xử lý selfdestruct (vì hành vi xóa đã được cập nhật).
Mọi opcode đều tốn Năng lượng. Viết mã Solidity tối ưu gas cho Ethereum sẽ tạo ra các hợp đồng tối ưu Năng lượng trên TRON một cách tương tự — các nguyên lý là giống nhau. (Dành cho nhà phát triển Web2: Tối ưu hóa mức sử dụng gas giống như việc tối ưu hóa các truy vấn cơ sở dữ liệu đắt đỏ. Trên các máy chủ truyền thống, các truy vấn tồi chỉ làm chậm mọi thứ; trên các blockchain, chúng trực tiếp tiêu tốn tiền thật của người dùng của bạn).
config =Config(a, b, c); // một lần gọi SSTORE duy nhất cho một khe cắm
}
Sử dụng các hàm view và pure để đọc dữ liệu. Các lệnh gọi View/pure không tốn Năng lượng khi được gọi off-chain (chúng miễn phí). Chỉ những lệnh gọi làm thay đổi trạng thái mới tốn Năng lượng.
Phát các Sự kiện (Events) thay vì ghi vào bộ nhớ cho các dữ liệu lịch sử. Các Sự kiện được lưu trữ trong nhật ký (rẻ) thay vì trong bộ nhớ hợp đồng (đắt).
Sử dụng calldata thay vì memory cho các tham số hàm khi dữ liệu chỉ để đọc và không bị thay đổi:
MemoryUsage.sol
// Task: Tránh sao chép các mảng lớn vào bộ nhớ (memory) nếu chỉ để đọc.
Xác thực mã nguồn hợp đồng của bạn trên TRONSCAN cho phép người dùng và các nhà phát triển khác đọc logic của bạn, kiểm tra ABI và tương tác trực tiếp thông qua trình khám phá khối.
Các bước xác thực
Điều hướng đến địa chỉ Hợp đồng của bạn trên tronscan.org
Nhấp vào tab Contract
Nhấp vào Verify and Publish
Chọn phiên bản trình biên dịch được sử dụng bởi TronBox (phải khớp chính xác)
Dán mã nguồn Solidity của bạn vào
Gửi đi — TRONSCAN sẽ biên dịch và xác minh xem bytecode có khớp trên mạng lưới (on-chain) hay không
Đối với các dự án có nhiều tệp (multi-file), hãy sử dụng phương pháp Standard JSON Input, chấp nhận đầu vào của trình biên dịch đầy đủ bao gồm tất cả các tệp được nhập (imported). Đầu ra build/contracts/*.json của TronBox chứa thông tin đầu vào trình biên dịch cần thiết.
Để biết thông tin phân tích đầy đủ về cách Năng lượng và Băng thông hoạt động, hệ số nhân của Mô hình Năng lượng Động (DEM), và cách triển khai ủy quyền phí để dApp của bạn trợ cấp chi phí cho người dùng, hãy xem Mô hình phí & Ủy quyền.
Mọi giao dịch gọi đến một Hợp đồng đều chỉ định một giới hạn phí (fee limit) — mức TRX tối đa mà người gửi sẵn sàng đốt nếu Năng lượng cạn kiệt. Nếu việc thực thi Hợp đồng vượt quá Năng lượng khả dụng và chạm đến giới hạn phí, giao dịch sẽ hoàn tác (reverts) và một phần của giới hạn phí bị tiêu thụ.
Trong tronweb, hãy đặt giới hạn phí cho mỗi lần gọi:
sdk_call.js
// Task: Chỉ định một giới hạn phí để bảo vệ khỏi các vòng lặp vô hạn/chi phí cao.
awaitcontract.someMethod().send({
feeLimit: 1_000_000_000, // Tối đa 1,000 TRX
shouldPollResponse: true,
});
Hãy đặt một mức giới hạn phí rộng rãi trong quá trình phát triển và thắt chặt nó lại sau khi bạn biết chính xác chi phí Năng lượng thực tế từ lịch sử giao dịch TRONSCAN.
Tất cả các logic dựa trên thời gian đều phải sử dụng mili-giây, chứ không phải giây. Hãy kiểm toán mọi phép so sánh block.timestamp trong các Hợp đồng được di trú.
Hành vi SELFDESTRUCT
Cần lưu ý hành vi SELFDESTRUCT mới (Đề xuất 106): các Hợp đồng không còn bị xóa nữa trừ khi chúng bị hủy ngay trong giao dịch khởi tạo ra chúng. Điều chỉnh logic nâng cấp và dọn dẹp của bạn sao cho phù hợp.
Tính toán địa chỉ off-chain
Nếu các tập lệnh triển khai của bạn tính toán các địa chỉ hợp đồng off-chain (cho các CREATE factories), hãy tính toán lại theo sơ đồ dẫn xuất địa chỉ của TRON.
Đánh giá thấp Năng lượng
Luôn thử nghiệm mức tiêu thụ Năng lượng trên mạng Nile trước khi lên mainnet. Việc đánh giá thấp giới hạn phí sẽ gây ra các lần hoàn tác (reverts) vào những thời điểm tồi tệ nhất.