Cheat sheet Solidity
Cấu trúc contract
Mỗi tệp bắt đầu bằng giấy phép và pragma; contract là đơn vị để triển khai.
| Cú pháp | Ý nghĩa |
|---|---|
// SPDX-License-Identifier: MIT | Chú thích giấy phép mà trình biên dịch yêu cầu ở dòng 1 |
pragma solidity ^0.8.0; | Phiên bản trình biên dịch mà tệp được viết cho |
contract Counter { ... } | Khai báo contract (state và hàm) |
constructor(uint start) { count = start; } | Chạy một lần, lúc triển khai |
import "./Token.sol"; | Import một tệp khác |
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | Import một package thư viện |
interface IToken { function balanceOf(address a) external view returns (uint); } | Khai báo interface (không có thân hàm) |
library Math { function min(uint a, uint b) internal pure returns (uint) { ... } } | Thư viện gồm các hàm dùng lại được |
Kiểu giá trị
Số nguyên có kích thước cố định và không có phần thập phân; 0.8 sẽ revert khi tràn số.
| Kiểu | Giá trị chứa được |
|---|---|
uint256 / uint | Số nguyên không dấu, từ 0 đến 2^256 - 1 (uint là uint256) |
uint8, uint16, ... uint128 | Số nguyên không dấu nhỏ hơn, theo bước 8 bit |
int256 / int | Số nguyên có dấu (cho phép số âm) |
bool | true hoặc false |
address | Địa chỉ tài khoản hoặc contract dài 20 byte |
address payable | Địa chỉ có thể nhận Ether qua transfer/send |
bytes32, bytes1... | Mảng byte có kích thước cố định |
enum Status { Open, Closed } | Tập hằng số có tên, lưu dưới dạng uint8 |
1 ether, 1 gwei, 1 wei | Đơn vị Ether: 1 ether = 10^18 wei |
1 days, 2 hours, 30 minutes | Đơn vị thời gian, tính bằng giây |
Kiểu tham chiếu và vị trí dữ liệu
Mảng, chuỗi, bytes, struct và mapping nằm ở storage, memory hoặc calldata.
| Cú pháp | Ý nghĩa |
|---|---|
string memory name | Chuỗi UTF-8 động (một bản sao tạm thời) |
bytes memory data | Mảng byte động |
uint[] public scores; | Mảng động trong storage |
uint[3] fixed; | Mảng cố định 3 phần tử |
uint[] memory tmp = new uint[](5); | Cấp phát một mảng trong memory |
scores.push(42); | Thêm phần tử vào mảng storage |
scores.pop(); | Xóa phần tử cuối |
scores.length | Số phần tử |
storage | Lưu lâu dài trên chuỗi, ghi tốn phí cao |
memory | Tạm thời, chỉ tồn tại trong một lần gọi |
calldata | Đầu vào chỉ đọc của hàm external, rẻ nhất |
Mapping và struct
Mapping là bảng băm không có độ dài và không duyệt được; struct gom các trường lại với nhau.
| Cú pháp | Ý nghĩa |
|---|---|
mapping(address => uint) public balances; | Kho khóa và giá trị, mọi khóa đều tồn tại (mặc định là 0) |
balances[msg.sender] += 1; | Đọc/ghi theo khóa |
mapping(address => mapping(address => uint)) allowance; | Mapping lồng nhau |
struct User { string name; uint age; bool active; } | Định nghĩa struct |
User memory u = User("Ada", 36, true); | Tạo struct trong memory |
User memory u = User({name: "Ada", age: 36, active: true}); | Tạo theo tên trường |
users[msg.sender] = u; | Lưu struct vào mapping |
users[msg.sender].age = 37; | Cập nhật một trường trong storage |
delete users[msg.sender]; | Đặt lại về giá trị mặc định |
Hàm và visibility
Mỗi hàm khai báo ai được gọi nó và nó đọc hay ghi state.
| Cú pháp | Ý nghĩa |
|---|---|
function add(uint a, uint b) public pure returns (uint) { return a + b; } | Hàm có tham số và giá trị trả về |
public | Gọi được từ mọi nơi (bên trong lẫn bên ngoài) |
external | Chỉ gọi được từ bên ngoài contract |
internal | Contract này và các contract kế thừa nó |
private | Chỉ contract này |
view | Đọc state, không bao giờ ghi |
pure | Không đọc state nào cả |
payable | Có thể nhận Ether cùng lời gọi |
returns (uint sum, bool ok) | Nhiều giá trị trả về có tên |
(uint s, bool ok) = f(); | Phân rã nhiều giá trị trả về |
uint public count; | Biến state public tự có hàm getter count() |
Modifier, hằng số và kế thừa
Dùng lại các bước kiểm tra bằng modifier; cố định giá trị bằng constant và immutable.
| Cú pháp | Ý nghĩa |
|---|---|
modifier onlyOwner() { require(msg.sender == owner, "Not owner"); _; } | Định nghĩa modifier (_ = chạy thân hàm) |
function withdraw() public onlyOwner { ... } | Áp dụng modifier |
uint public constant MAX = 100; | Hằng số lúc biên dịch |
address public immutable owner; | Gán một lần trong constructor, sau đó cố định |
contract Token is ERC20, Ownable { ... } | Kế thừa từ các contract khác |
function f() public virtual { ... } | Cho phép ghi đè |
function f() public override { ... } | Ghi đè hàm của contract cha |
super.f(); | Gọi phần cài đặt của contract cha |
abstract contract Base { function f() public virtual; } | Contract có các hàm chưa cài đặt |
Luồng điều khiển
Các câu lệnh quen thuộc của họ ngôn ngữ C; không có switch, và mỗi lần lặp đều tốn gas.
| Cú pháp | Ý nghĩa |
|---|---|
if (x > 5) { ... } else if (x > 2) { ... } else { ... } | Rẽ nhánh theo điều kiện |
for (uint i = 0; i < n; i++) { ... } | Vòng lặp đếm |
while (x < 10) { x++; } | Lặp khi điều kiện còn đúng |
do { ... } while (cond); | Chạy ít nhất một lần |
break; / continue; | Thoát vòng lặp / bỏ qua sang lần lặp tiếp theo |
x > 0 ? a : b | Biểu thức ba ngôi |
a / b | Chia lấy phần nguyên (bỏ phần dư) |
a % b | Phần dư |
a ** 2 | Lũy thừa |
unchecked { x++; } | Bỏ qua kiểm tra tràn số (tiết kiệm gas, dùng cẩn thận) |
Lỗi: require, revert, assert
Một bước kiểm tra thất bại sẽ hoàn tác toàn bộ giao dịch và hoàn lại phần gas chưa dùng.
| Cú pháp | Ý nghĩa |
|---|---|
require(amount > 0, "Amount must be positive"); | Kiểm tra đầu vào hoặc state; revert kèm thông báo |
revert("Not allowed"); | Hủy ngay vô điều kiện |
error Insufficient(uint available, uint requested); | Khai báo lỗi tùy chỉnh (rẻ hơn dùng chuỗi) |
revert Insufficient(balance, amount); | Revert bằng lỗi tùy chỉnh |
assert(total == a + b); | Kiểm tra một bất biến không bao giờ được sai |
try token.transfer(to, amt) returns (bool ok) { ... } catch { ... } | Xử lý lời gọi bên ngoài bị lỗi |
Event
Event ghi log để các ứng dụng ngoài chuỗi đăng ký theo dõi; contract không đọc được event.
| Cú pháp | Ý nghĩa |
|---|---|
event Transfer(address indexed from, address indexed to, uint value); | Khai báo event |
emit Transfer(msg.sender, to, amount); | Phát event |
indexed | Tham số lọc được (tối đa 3 tham số mỗi event) |
event Log(string message); | Ghi log được mọi kiểu ABI |
Ether, địa chỉ và biến toàn cục
Ngữ cảnh giao dịch lấy từ msg, block và tx.
| Cú pháp | Ý nghĩa |
|---|---|
msg.sender | Địa chỉ đã gọi hàm này |
msg.value | Số wei gửi kèm lời gọi (cần payable) |
block.timestamp | Thời gian của block hiện tại (số giây tính từ epoch) |
block.number | Chiều cao block hiện tại |
tx.origin | Tài khoản sở hữu bên ngoài đã khởi tạo giao dịch (tránh dùng để xác thực) |
address(this).balance | Số dư Ether của contract này |
payable(to).transfer(1 ether); | Gửi Ether, revert khi thất bại |
(bool ok, ) = to.call{value: amt}(""); | Gửi ở mức thấp, trả về cờ thành công |
receive() external payable {} | Chạy khi nhận Ether chuyển thẳng |
fallback() external payable {} | Chạy khi không có hàm nào khớp |
keccak256(abi.encodePacked(a, b)) | Tính giá trị băm |
abi.encode(x), abi.decode(data, (uint)) | Mã hóa / giải mã dữ liệu ABI |
Mọi cú pháp Solidity bạn hay dùng, gom trong một trang. Cheat sheet Solidity này là bảng tra cứu nhanh cho ngôn ngữ smart contract của Ethereum và mọi chuỗi EVM: khai báo contract, chọn kiểu dữ liệu, lưu dữ liệu trong mapping và struct, viết hàm với visibility và mutability phù hợp, rồi bảo vệ chúng bằng require, modifier và event.
Cú pháp ở đây là Solidity 0.8, phiên bản mặc định kiểm tra tràn số học và dùng được với Remix, Hardhat và Foundry. Sao chép phần bạn cần, hoặc thử ngay trong playground Solidity: viết contract, biên dịch rồi chạy trên EVM ngay trong trình duyệt.
Solidity cheat sheet FAQ
Is this Solidity cheat sheet free?
Yes. This cheat sheet is free to use, with no sign-up required. Bookmark it and come back any time you need a quick reference.
Is this cheat sheet good for beginners?
Yes. It is organized by topic so you can find what you need at any level, and each entry links back to Coddy's free interactive Solidity course when you want to go deeper.