Solidity basic 1
date
Aug 9, 2024
slug
solidity-basic-1
status
Published
tags
Solidity
summary
Solidity basic 1
type
Post
- Bố cục Solidity Source File
Tại sao phải có giấy phép? Một cách đơn giản thì giấy phép giúp cho code của bạn được chứng nhận là mã nguồn mở. Vì code trong các smart contract trên blockchain là public, ai cũng có thể xem code.
Bằng cách thêm giấy phép vào mã nguồn của bạn, bạn xác nhận rằng mã đó là mã nguồn mở, cho phép người khác sử dụng, sửa đổi và phân phối lại theo các điều khoản mà bạn đã chọn. Điều này không chỉ giúp bảo vệ quyền lợi của bạn mà còn thúc đẩy sự phát triển cộng đồng, bởi vì người khác có thể đóng góp và cải thiện mã nguồn của bạn.
- Pragma Version: xác định phiên bản giúp cố định mã nguồn của contract ở một hoặc vài phiên bản Solidity nhất định.
Bởi vì Solidity liên tục cập nhật với các tính năng mới, cải tiến hiệu suất và sửa lỗi. Xác định version cho contract giúp đảm bão mã được biên dịch và chạy chính xác, không gặp phải các vấn đề không tương thích của các phiên bản cập nhật mới hơn.
- Những kiểu dữ liệu (type) cơ bản của Solidity
uint256: số nguyên dương, có giá trị từ 0 đổ lên. Mặc định là số 0.
int256: số nguyên, có thể có giá trị âm, dương, hoặc bằng 0. Mặc định là số 0.
bool: đúng hoặc sai,truehoặcfalse. Mặc định làfalse.
string: chuỗi ký tự, độ dài của chuỗi không được cố định và có thể thay đổi. Thường dùng để lưu văn bản. Mặc định là chuỗi rỗng.
bytes: dùng để lưu dữ liệu nhị phân, không phải là văn bản.byteslà kiểu dữ liệu động, độ dài có thể thay đổi, cònbytes32là kiểu dữ liệu tĩnh, có độ dài cố định. Mặc định là rỗng.
address: địa chỉ address, dùng để xác định người dùng, các hợp đồng trong mạng lưới blockchain. Mặc định làaddress(0)0x0000000000000000000000000000000000000000
- Functions
Visibility: public, external, internal, private.public có thể gọi function trong hợp đồng ở đâu cũng được, không có giới hạn.external chỉ có thể gọi từ bên ngoài vào trong hợp đồng.internal có thể gọi từ bên trong hợp đồng và từ các hợp đồng được kế thừa.private chỉ có thể gọi bên trong hợp đồng mà không thể gọi từ hợp đồng con được kế thừa nào.Deploy một contract (smart contract có một địa chỉ address cũng giống như wallet của chúng ta).view & pure functions.
- Array
contract Array { // Một số cách để khởi tạo một array uint256[] public arr; // Array rỗng uint256[] public arr2 = [1, 2, 3]; // Array fixed size, độ dài cố định, các phần tử mặc định giá trị 0 uint256[10] public myFixedSizeArr; function get(uint256 i) public view returns (uint256) { return arr[i]; } // Solidity có thể return về hết một cả array bất kể độ dài // Nên tránh returns theo kiểu này, vì array có thể rất lớn function getArr() public view returns (uint256[] memory) { return arr; } function push(uint256 i) public { // Thêm vào array, độ dài của array sẽ tăng lên một arr.push(i); } function pop() public { // Xoá phần tử cuối cùng của array // Độ dài của array sẽ giảm đi 1 arr.pop(); } function getLength() public view returns (uint256) { return arr.length; } function remove(uint256 index) public { // Delete sẽ không xoá phần tử trong array tại vị trí index // Nó sẽ đưa giá trị của phần tử về giá trị mặc định // Ở đây giá trị mặc định của unit256 là 0 delete arr[index]; } function examples() external { // Tạo một biến array trong phân vùng memory để tính toán dữ liệu // Sẽ bị xoá đi khi function hoàn tất // Chỉ có thể khởi tạo kiểu này với fixed size array uint256[] memory a = new uint256[](5); } }
Struct
contract Todos { struct Todo { string text; bool completed; } // Một array với kiểu `Todo` Todo[] public todos; function create(string calldata _text) public { // 3 cách để khởi tạo một struct // - gọi nó như một function todos.push(Todo(_text, false)); // key value mapping todos.push(Todo({text: _text, completed: false})); // khởi tạo một struct rỗng và update đó Todo memory todo; todo.text = _text; // todo.completed khởi tạo sẽ bằng giá trị mặc định của kiểu dữ liệu // ở đây = false todos.push(todo); } // update text function updateText(uint256 _index, string calldata _text) public { Todo storage todo = todos[_index]; todo.text = _text; } // update completed function toggleCompleted(uint256 _index) public { Todo storage todo = todos[_index]; todo.completed = !todo.completed; } }
Memory, Storage & Calldata
Stack: Đây là nơi các giá trị được lưu trữ tạm thời trong quá trình thực thi các hàm. EVM sử dụng một stack LIFO (Last In, First Out), có thể chứa các số nguyên (integer) và địa chỉ (address). Mọi phép toán trong EVM đều được thực hiện trên stack. Memory: Đây là không gian lưu trữ tạm thời được sử dụng để thực hiện các phép toán phức tạp như chuỗi (string) hoặc mảng động (dynamic array). Memory trong EVM là không gian dữ liệu có thể truy cập và được phân bổ trong quá trình thực thi, xoá đi sau khi thực thi hoàn tất. Storage: Đây là vị trí lưu trữ dữ liệu có tính khả dụng lâu dài nhất trong EVM. Storage được sử dụng để lưu trữ các giá trị dữ liệu trên blockchain Ethereum. Các biến được lưu trữ trong storage có thể được truy cập và cập nhật trong nhiều lần gọi hàm khác nhau và tồn tại cho đến khi hợp đồng bị xoá hoặc thay đổi bởi hợp đồng khác. Calldata: Đây là không gian lưu trữ dữ liệu chỉ đọc được từ các hàm ngoài hợp đồng. Calldata chứa các tham số và dữ liệu được truyền tới hợp đồng thông minh từ các giao dịch. Dữ liệu trong calldata không thể thay đổi bởi hợp đồng thông minh và chỉ có thể đọc. Code: Đây là mã bytecode của một hợp đồng thông minh Ethereum, tức là mã máy ảo Ethereum (EVM bytecode) mà EVM sẽ thực thi khi một hợp đồng được triển khai lên blockchain. Code này được lưu trữ trong blockchain và xác định hành vi và chức năng của hợp đồng thông minh. Logs: Đây là một công cụ để ghi lại và truy cập các sự kiện (events) xảy ra trong một hợp đồng thông minh. Logs được lưu trữ như là một phần của bản ghi giao dịch trong blockchain. Chúng là các dữ liệu không thể thay đổi và có thể được truy cập bởi các ứng dụng và dịch vụ khác để theo dõi và phân tích các sự kiện xảy ra trong hợp đồng thông minh. Có 6 loại nhưng memory, storage & calldata là 3 loại mà chúng ta tiếp xúc nhiều nhất khi chúng ta làm việc với smart contract.
Mappings
mapping là một loại cấu trúc dữ liệu được sử dụng để lưu trữ cặp key-value, cho phép bạn ánh xạ một giá trị (value) tới một key (khóa) duy nhất và không thứ tự.