Solidity là gì?
Giới thiệu
Solidity là một ngôn ngữ lập trình cao cấp dùng cho ứng dụng trong smart contract. Được thiết kế đặc biệt cho Ethereum Virtual Machine, đây là một ngôn ngữ hướng đối tượng. Hãy cùng tìm hiểu về nó.
Let’s go!!!
Đầu tiên, chúng ta cần tạo một file Contract.sol.
Trước tiên, hãy xác định phiên bản Solidity bạn đang sử dụng. Đây là thông tin mà trình biên dịch cần.
pragma solidity ^0.4.22;
Mọi mã trong Ethereum đều thuộc về một Contract. Hãy tạo một contract và xác định một số biến trong đó.
pragma solidity ^0.4.22;
contract DeveloperFactory {
// Hãy tạo một Developer!
uint dnaDigits = 16;
uint ageDigits = 2;
}
Solidity là một ngôn ngữ kiểu tĩnh, có nghĩa là các biến phải được khai báo và xác định trước khi sử dụng. Các biến trong đoạn mã trên là state variables, tức là các thuộc tính sẽ được lưu trữ trong contract storage (trên Ethereum Blockchain). uint đại diện cho Unsigned Integer (số nguyên không âm). Do đó, Developer của chúng ta có một “dna” gồm 16 chữ số và một “age” có 2 chữ số.
Một số ghi chú thêm:
Trong Solidity, mọi thứ xoay quanh contract, giống như trong các ngôn ngữ hướng đối tượng (với contract là đối tượng cụ thể). Contract tương tự như một class trong OOP với các state variables (thuộc tính) và methods (phương thức). Ngoài khái niệm Contract, Solidity còn cung cấp 2 thuật ngữ khác tương tự Contract:
-
interface: Đặc tả cấu trúc của một hợp đồng, bao gồm các hàm không có thân hàm. Đây không xa lạ với các lập trình viên.
-
library: Được triển khai một lần và được sử dụng bởi các hợp đồng khác thông qua DELEGATECALL.
Struct và các array
pragma solidity ^0.4.22;
contract DeveloperFactory {
// Hãy tạo một Developer!
uint dnaDigits = 16;
uint ageDigits = 2;
struct Developer {
string name;
uint dna;
uint age;
}
Developer[] public developers;
}
Biến struct cho phép chúng ta xác định nhiều cấu trúc dữ liệu hơn. Trong ví dụ trên, Developer có một chuỗi được gọi là “name”, một số nguyên “dna” và một số nguyên “age”.
Solidity cũng hỗ trợ các array. Bạn có thể tạo các array cố định hoặc linh hoạt. Mảng Developer của chúng ta là một mảng linh hoạt, không có giới hạn về độ dài. Chúng ta có thể thêm vào bao nhiêu Developer tùy ý.
Mảng Developer[5] public developers là một mảng cố định có thể chứa tối đa 5 cấu trúc Developer.
Các function
Một function trong Solidity sẽ có dạng như sau:
pragma solidity ^0.4.22;
contract DeveloperFactory {
// Hãy tạo một Developer!
uint maxAge = 100;
uint minAge = 5;
struct Developer {
string name;
uint id;
uint age;
}
Developer[] public developers;
function _createDeveloper(string _name, uint _id, uint _age) private {
developers.push(Developer(_name, _id, _age));
}
function _generateRandomId(string _str) private pure returns (uint) {
uint rand = uint(keccak256(_str));
return rand;
}
function createRandomDeveloper(string _name, uint _age) public view {
require(_age > minAge);
require(_age < maxAge);
uint randId = _generateRandomId(_name);
_createDeveloper(_name, randId, _age);
}
}
Chúng ta tạo các function bằng keyword “function”. Các function có thể nhận các tham số và mặc định là public. Tôi đã thêm keyword private vào function để làm cho nó private. Tôi cũng thêm dấu gạch dưới “_” trước private function hoặc biến để phân biệt chúng với các biến và function public. Việc này không bắt buộc, chỉ là tôi nghĩ rằng nó sẽ dễ đọc hơn.
Ethereum có một hash function keccak256 có sẵn, một phiên bản của SHA3. Hãy cung cấp cho nó một chuỗi bất kỳ và bạn sẽ nhận được một số hexadecimal 256-bit.
Như bạn có thể thấy, chúng ta chuyển đổi kiểu dữ liệu từ keccak256 thành kiểu uint và trả về nó.
Ngoài keyword private, bạn cần thêm một số điều vào function:
-
Sử dụng keyword “returns” và xác định kiểu dữ liệu mà function trả về. Trong ví dụ này, function trả về một số nguyên uint.
-
Sử dụng keyword “view” để chỉ định rằng function chỉ xem các biến trong Contract mà không thay đổi chúng. Function createRandomDeveloper cần xem các biến minAge và maxAge.
-
Sử dụng keyword “pure” để chỉ định rằng function không truy cập vào bất kỳ dữ liệu nào trong ứng dụng. Function _generateRandomId là một ví dụ cho pure function.
Chúng ta có 3 function như sau:
-
_generateRandomId tạo ra một id ngẫu nhiên cho Developer của chúng ta bằng cách sử dụng function keccak256 có sẵn.
-
_createDeveloper tạo và thêm một struct Developer mới vào mảng.
-
createRandomDeveloper là public function duy nhất. Nó kiểm tra xem age được cung cấp có hợp lệ không. Các câu lệnh require sẽ báo lỗi nếu không hợp lệ (age lớn hơn 100 hoặc nhỏ hơn 5 trong trường hợp này). Đây là function cuối cùng mà bạn có thể gọi từ bên ngoài contract.
Các event
Bạn có thể tạo các event để tương tác với những gì diễn ra trên blockchain và hiển thị chúng trên giao diện người dùng. Ứng dụng của bạn sẽ dựa trên các event này và phản ứng tương ứng.
pragma solidity ^0.4.22;
contract DeveloperFactory {
// Hãy tạo một Developer!
event NewDeveloper(uint devId, string name, uint age);
uint maxAge = 100;
uint minAge = 5;
struct Developer {
string name;
uint id;
uint age;
}
Developer[] public developers;
function _createDeveloper(string _name, uint _id, uint _age) private {
uint id = developers.push(Developer(_name, _id, _age)) - 1;
emit NewDeveloper(id, _name, _age);
}
function _generateRandomId(string _str) private pure returns (uint) {
uint rand = uint(keccak256(_str));
return rand;
}
function createRandomDeveloper(string _name, uint _age) public view {
require(_age > minAge);
require(_age < maxAge);
uint randId = _generateRandomId(_name);
_createDeveloper(_name, randId, _age);
}
}
Chúng ta tạo event bằng keyword “event”. Trong Contract, event sẽ có 3 tham số bao gồm devId, name và age. Chúng ta kích hoạt event trong function _createDeveloper. Id được nhận từ phương thức push trên mảng Developer. Phương thức này trả về một độ dài mới của mảng. Vì mảng bắt đầu từ 0, chúng ta phải trừ đi 1 để có được id của developer.
Kết luận
Một số khái niệm cơ bản về Solidity đã được sáng tỏ. Trong phần tiếp theo, chúng ta sẽ tiếp tục khám phá những khái niệm sâu hơn về khả năng của Solidity.
Phần 2: Học về Solidity cơ bản >>