Solidity cơ bản – Tạo 1 Contract cơ bản (P1)

<< Solidity là gì?

Giới thiệu

Solidity là một ngôn ngữ high-level dùng cho ứng dụng vào smart contract. Nó là một ngôn ngữ hướng đối tượng được thiết kế dành riêng cho Ethereum Virtual Machine. Hãy cùng tìm hiểu nó.

Let’s go!!!

Đầu tiên tạo một file Contract.sol

Đầu tiên bạn phải xác định phiên bản bạn đang dùng. Đây là info mà compiler cần.

pragma solidity ^0.4.22;

Mọi code trong Ethereum đều thuộc về một Contract. Hãy tạo một contract và xác định một vài variable trong đó.

pragma solidity ^0.4.22;

contract DeveloperFactory {
    // Let's create a Developer!
    uint dnaDigits = 16;
    uint ageDigits = 2;
}

Solidity là một typed language (ngôn ngữ kiểu tĩnh: là những ngôn ngữ mà các variable cần phải định danh trước khi được sử dụng. Có nghĩa là variable cần phải khai báo và khởi tạo trước). Các biến trong đoạn code trên là state variables, các thuộc tính này sẽ được lưu trong contract storage (trong Ethereum Blockchain). uint là đại diện cho kiểu dữ liệu Unsigned Integer (số nguyên không âm), quay trở lại đoạn code trên ta có Developer của chúng ta có 1 dna gồm 16 chữ số và 1 age có 2 chữ số.

Note thêm: Trong Solidity mọi thứ đều xoanh quanh contract, cũng tương tự như các ngôn ngữ hướng đối tượng (đối tượng cụ thể ở đây là contact). Về cơ bản, contract tương tự class trong OOP với các thuộc tính (state variables) và các phương thức (methods). Ngoài khái niệm Contract, Solidity cũng cung cấp 2 đối tượng khác tương tự Contract bao gồm:

  • interface: Đặc tả cấu trúc của hợp đồng, bao gồm các hàm mà không có thân hàm, không xa lạ với giới lập trình viên nên có lẽ không cần giải thích nhiều.
  • library: Deploy 1 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 {
    // Let's create a 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 data hơn. Ở đây Developer lấy một string được gọi là name, một uint tên dna và một uint tên age.

Solidity cũng có các array. Bạn có thể tạo các array cố định hoạt linh hoạt tùy ý. Mãng Developer của chúng ta là linh hoạt vì không xác định chiều dài. Vì thế chúng ta có thể add thêm các Developer vào vô số mà không có giới hạn.

Developer[5] public developers là một array cố định có thể chứa đến 5 Developer struct.

Các function

Một function trông như sau:

pragma solidity ^0.4.22;

contract DeveloperFactory {
    // Let's create a 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 các function keyword. Các function có thể nhận các parameter. Và các function mặc định là public. Tôi đã add private keyword để làm cho function private. Ngoài ra tôi cũng add một underscore (là dấu gạch chân _ ) trước private function hoặc variable để phân biệt nó với các public variables. Việc này không bắt buộc, chỉ là tôi nghĩ nó sẽ dễ đọc hơn.

Ethereum có một hash function keccak256 có sẵn, nó là một phiên bản của SHA3. Pass cho nó string bất kì và bạn sẽ có được một số lục phân 256-bit.

Như bạn có thể thấy, chúng ta đều type-casting (chuyển đổi kiểu dữ liệu) từ keccak256 value sang uint value và return nó.

Ngoài private keyword, bạn cần phải add thêm vài thứ vào function:

  • Hãy dùng returns và xác định dạng mà function return. Ở đây nó trả về một dạng uint.
  • view nghĩa là function cần xem một vài biến của Contract, mà không được thay đổi nó. Ở đây Function createRandomDeveloper cần xem các biến minAge and maxAge.
  • pure nghĩa là function không truy cập vào bất kì data trong app. Nó chỉ trả về cái gì đó dựa trên các parameter, _generateRandomId chính là pure.

Chúng ta có 3 function là:

 _generateRandomId tạo ra một Id ngẫu nhiên cho Developer của chúng ta bằng cách dùng function keccak256 sẵn có.

 _createDeveloper tạo và push một Developer struct mới thành mảng.

createRandomDeveloper là public function duy nhất. Nó sẽ check xem age được cung cấp có đúng hay không. Các câu lệnh require sẽ báo error nếu nó không đúng (age lớn hơn 100 và ít hơn 5 trong trường hợp này). Từ đó, function cuối là cái có thể được call từ ngoài contract.

Các event

Bạn có thể tạo các event để có thể tương tác với những gì diễn ra trên blockchain và show trên front end. App của bạn sẽ dựa theo các event và phản hồi theo đó.

pragma solidity ^0.4.22;

contract DeveloperFactory {
    // Let's create a 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;
        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 event. Trong Contract, event sẽ có 3 parameter bao gồm devId, nameage. Chúng ta sẽ kích hoạt event trong hàm _createDeveloper. Id được lấy từ phương thức push trên mảng Developer. Nó sẽ trả về một độ dài mới cho mảng. Vì array bắt đầu 0, chúng ta phải trừ đi 1 để lấy developer id.

Note: Series này được truyền cảm hứng từ tutorial của CryptoZombies.

Note bis: Bạn có thể dùng Remix IDE trong browser của bạn nếu bạn muốn khám phá thêm Solidity.

Kết luận

Một số concept căn bản của Solidity đã sáng tỏ. Trong bài viết tiếp theo, chúng ta sẽ chuyển sang tìm hiểu các concept sâu hơn về những khả năng của Solidity.

Phần 2: Học về Solidity cơ bản >>