Blockchain cơ bản – Học về Solidity (P2)
Trong bài trước chúng ta đã khởi động bằng một số concept cơ bản của Solidity bằng cách tạo một contract đơn giản và khám phá một số cấu trúc cùng concept đơn giản. Bây giờ chúng ta sẽ tiếp tục bằng một số concept phức tạp hơn.
Các Mapping
Tiếp nối struct
và arrays
, chúng ta còn có thể lưu trữ data trên các mapping
. Các mapping là nơi chứa key-value. Ví dụ:
mapping(uint => string) public keyUintStringValue; mapping(address => uint) public addressToUint;
Chúng ta có 2 public mapping. Cái đầu có uint
key và string
value. Cái thứ 2 có address
key và uint
value.
Addresses
Ethereum blockchain được tạo nên từ các address. Mỗi account có một address riêng. Nó có dạng dưới đây: 0x0cE440255306E921F41612C46F1v6df9Cc969183
. Mỗi address có một lượng Ether nhất định, là số cryptocurrency được dùng trên blockchain, và có thể cho và nhận Ether từ các address khác.
Từ đó tạo một mapping mới cho DeveloperFactory
:
pragma solidity ^0.4.22; contract DeveloperFactory { 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; mapping (address => uint) public ownerDevCount; mapping (uint => address) public devToOwner; function _createDeveloper( string _name, uint _id, uint _age ) private{ uint id = developers.push( Developer( _name, _id, _age ) ) - 1; 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 ); } }
Trong mapping đầu tiên, chúng ta sẽ theo dõi số dev trong mỗi account (address) có. Ngay sau đó sẽ theo dõi được owner cho mỗi dev.
msg.sender
Mỗi contract đều khá bị động, nó sẽ không làm gì trừ phi có ai đụng tới. msg.sender
là một global variable cho chúng ta biết address nào phụ trách việc kích hoạt. Nó có thể là account hoặc là một smart contract khác.
Với thông tin này, chúng ta có thể update mapping của mình một cách hợp lí. Trên function _createDeveloper
, chúng ta sẽ tăng ownerDevCount
cho riêng address này. Trong mapping devToOwner
, chúng ta phải chỉ ra developer mới tạo được sở hữu bởi msg.sender
address.
pragma solidity ^0.4.22; contract DeveloperFactory { 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; mapping (address => uint) public ownerDevCount; mapping (uint => address) public devToOwner; function _createDeveloper( string _name, uint _id, uint _age ) private{ uint id = developers.push( Developer( _name, _id, _age ) ) - 1; ownerDevCount[msg.sender]++; devToOwner[id] = msg.sender; 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 ); } }
Hãy lưu ý kí hiệu ++ để tăng ownerDevCount[msg.sender]
, giống y như Javascript!
Inheritance và import
Các contract có thể kế thừa từ các contract khác. Nếu bạn mở file mới tên DeveloperLearning.sol
, nó cũng có thể kế thừa từ DeveloperFactory.sol
:
pragma solidity ^0.4.22; import "./DeveloperFactory.sol"; contract DeveloperLearning is DeveloperFactory { // I have now access to DeveloperFactory functions }
Hãy xem cách chúng ta import contract DeveloperFactory
(giả sử nó nằm cùng folder). Để được kế thừa từ nó, chúng ta dùng keyword is
.
payable
Để một contract nhận được ether
, chúng ta cần có keyword payable
trong function. Lượng gửi đi có thể access được trong global variable msg.value
. Vì thế phải đảm bảo đã gửi trước một lượng ether
nhất định trước khi tạo một developer:
pragma solidity ^0.4.22; contract DeveloperFactory { 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; mapping (address => uint) public ownerDevCount; mapping (uint => address) public devToOwner; function _createDeveloper( string _name, uint _id, uint _age ) private{ uint id = developers.push( Developer( _name, _id, _age ) ) - 1; ownerDevCount[msg.sender]++; devToOwner[id] = msg.sender; 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 payable { require(_age > minAge); require(_age < maxAge); require(msg.value == 5); uint randId = _generateRandomId( _name ); _createDeveloper(_name, randId, _age ); } }
Memory và Storage
Trong Solidity, có 2 chỗ lưu variable: trong storage hoặc trong memory. Một variable lưu trên memory chỉ là tạm thời, nó còn khi function được dùng đến, sau đó sẽ bị xoá. Một variable lưu trên storage thì ở đó vĩnh viễn. Bạn cũng không cần phải lo lắng về việc variable được lưu ở đâu, vì Solidity sẽ xử lý nó giúp bạn.
Ví dụ như, các state variable (maxAge, minAge, Developer), được khai báo ngoài function thì sẽ lưu trên storage. Các variables như randId, id, rand được store trên memory.
Tuy nhiên, trong một số trường hợp, bạn muốn cần chi tiết chỗ lưu một variable nhất định. Solidity sẽ show cho bạn bằng keyword memory
và storage
.
Tham khảo thêm vị trí tuyển lập trình blockchain lương cao tại đây
- B BenQ RD Series – Dòng Màn Hình Lập Trình 4k+ Đầu Tiên Trên Thế Giới
- F Framework nào tốt nhất cho dự án của bạn? – Checklist chi tiết
- K Kinh nghiệm xử lý responsive table hiệu quả
- S Stackoverflow là gì? Bí kíp tận dụng Stack Overflow hiệu quả
- 7 7 kinh nghiệm hữu ích khi làm việc với GIT trong dự án
- B Bài tập Python từ cơ bản đến nâng cao (có lời giải)
- B Bảo mật API là gì? Một số nguyên tắc và kỹ thuật cần biết
- H Hướng dẫn cài đặt và tự học lập trình Python cơ bản từ A-Z
- C Chinh Phục Phân Tích Dữ Liệu Với Pandas Trong Python: Hướng Dẫn Từng Bước
- D Display CSS là gì? Cách khai báo và sử dụng thuộc tính display trong CSS