Numbers
Kiểu dữ liệu uint giúp lưu các giá trị số nguyên không dấu.
Info
Trong Solidity,
uintthực chất là một alias củauint256.
Ngoài ra còn các kiểu dữ liệu số nguyên không dấu với ít bit hơn: uint8, uint16, uint32, etc.
Solidity cũng có hỗ trợ toán tử lũy thừa tương tự như Python:
uint x = 5 ** 2; // equal to 5^2 = 25Cũng như là các toán tử thao tác với bit: <<, >>.
Tip
Với một kiểu số nguyên
xbất kỳ, ta có thể sử dụngtype(x).minhoặctype(x).maxđể truy cập đến giá trị nhỏ nhất và giá trị lớn nhất mà kiểu đó có thể biểu diễn.
Structs
Struct trong Solidity khá tương tự với C++:
struct Person {
uint age;
string name;
}Để khai báo một struct với các giá trị khởi tạo thì ta dùng cú pháp sau:
Person person = Person(172, "Satoshi");Hoặc cú pháp sau:
Person person = Person({
age: 172,
name: "Satoshi"
});Theo mặc định, khi khai báo một biến struct là public thì trình biên dịch sẽ tự động tạo ra getter cho biến đó. Getter này khi được contract khác gọi sẽ trả về một tuple bao gồm các field bên trong struct.
Tuy nhiên, nếu ta viết một custom getter và trả về struct thì giá trị trả về là một struct dù cho nó được gọi nội bộ hay từ bên ngoài.
Person public person;
function customGetPerson() public returns(Person memory) {
return person; // return the whole struct
}Arrays
Solidity cũng có hai loại mảng tương tự như C/C++ là mảng tĩnh và mảng động.
uint[2] fixedArray; // array with a fixed length of 2 elements.
string[5] stringArray; // another fixed array, can contain 5 strings.
uint[] dynamicArray; // a dynamic array - has no fixed size, can keep growing.Ta có thể tạo mảng các struct và thêm vào mảng này một instance của struct bằng hàm push:
Person[] people; // dynamic Array, we can keep adding to it.
// Create a new person:
Person satoshi = Person(172, "Satoshi");
// Add that person to the array:
people.push(satoshi);Để reset mảng, ta có thể lặp qua từng phần tử và gán giá trị zero (giá trị mặc định của từng kiểu dữ liệu) cho chúng hoặc gán toàn bộ mảng bằng một mảng mới:
users = new users[]();String
Kiểu string ở trong Solidity về bản chất là một mảng động. Ta có thể sử dụng một mảng bytes để lưu chuỗi nhằm tối ưu tốc độ.
Để so sánh hai chuỗi, ta cần so sánh dạng hash của chúng:
bool comparison = keccak256(abi.encodePacked((str1))) == keccak256(abi.encodePacked((str2)));Lý do là vì bản chất của chuỗi là mảng các bytes, mặc dù có thể lặp qua từng phần tử của mảng bytes nhưng việc hash rồi so sánh lại nhanh hơn rất nhiều. Chú ý rằng hàm abi.encodePacked ở trên có tác dụng chuyển từ kiểu string sang kiểu bytes.
Seealso
Xem thêm về Keccak256.
Kể từ phiên bản 0.8.12, chúng ta có thể sử dụng hàm string.concat để nối chuỗi thay cho abi.encodePacked:
string.concat(s1, s2, ...)Mappings
Tương tự như dictionary trong các ngôn ngữ lập trình khác.
// For a financial app, storing a uint that holds the user's account balance:
mapping (address => uint) accountBalance;
// Or could be used to store / lookup usernames based on userId
mapping (uint => string) userIdToName;Mapping lưu dữ liệu theo cặp key-value.
Minh họa việc sử dụng mapping ở trong Solidity:
Nếu ta truy cập đến một key nào đó không có trong mapping, nó sẽ trả ra giá trị mặc định của values. Chẳng hạn như xét mapping accountBalance ở trên, giá trị mặc định nhận được sẽ là 0 (là giá trị mặc định của kiểu uint).
Hiện tại thì mapping có các hạn chế sau:
- Không hỗ trợ kiểm tra xem một key nào đó có tồn tại ở trong mapping hay không (vì nó trả ra giá trị mặc định nên ta không chắc được).
- Không thể sử dụng tham số có kiểu là mapping đối với các hàm
publichayexternal.
Address
Kiểu dữ liệu này giúp lưu trữ các loại địa chỉ có trong mạng lưới của Ethereum. Một địa chỉ sẽ được sở hữu bởi một cá nhân hoặc một smart contract nào đó.
Về bản chất, kiểu dữ liệu address là một số nguyên 20 bytes.
Biến msg Là một biến toàn cục, thuộc tính sender của msg giúp lưu địa chỉ của user hoặc smart contract đang gọi thực thi hàm hiện tại.
Note
Chú ý: một contract sau khi được deployed lên blockchain thì sẽ không tự hoạt động cho đến khi có một địa chỉ nào đó gọi các hàm của nó.
Ví dụ sử dụng msg.sender và cập nhật mapping:
mapping (address => uint) favoriteNumber;
function setMyNumber(uint _myNumber) public {
// Update our `favoriteNumber` mapping to store `_myNumber` under `msg.sender`
favoriteNumber[msg.sender] = _myNumber;
}
function whatIsMyNumber() public view returns (uint) {
// Retrieve the value stored in the sender's address
// Will be `0` if the sender hasn't called `setMyNumber` yet
return favoriteNumber[msg.sender];
}Default Values
Giá trị mặc định của các biến khi khai báo đều là giá trị 0. Ví dụ với bool thì là false, uint và int thì là 0.
Các phần tử trong mảng tĩnh sẽ có giá trị mặc định tùy thuộc vào kiểu của nó. Với mảng động hoặc string, giá trị mặc định sẽ là mảng rỗng hoặc chuỗi rỗng.
Giá trị mặc định của kiểu address là 0x0000000000000000000000000000000000000000.