KiemTienOnline360

Chia sẻ hành trình kiếm tiền online bắt đầu từ con số 0

Kiến thức lập trình, Kỹ nghệ phần mềm

Hướng dẫn lập trình và triển khai Smart Contract trên TRON network

Hướng dẫn lập trình và triển khai Smart Contract trên TRON network

Hướng dẫn lập trình và triển khai Smart Contract trên TRON network

Chia sẻ bài viết
0
(0)

Tìm hiểu một chút về hệ sinh thái TRON

TRON Network là một blockchain công khai, một mạng lưới phi tập trung được xây dựng bởi TRON Foundation. TRON Foundation được thành lập bởi giám đốc điều hành Justin Sun. TRON dựa trên cơ chế Proof-of-Stake được ủy quyền (DPoS), trong đó 27 Siêu Đại Diện (Super Representative) luân phiên nhau 6 giờ một lần để xác thực các block và giao dịch. Hợp đồng thông minh có thể được viết bằng Solidity và được biên dịch trên Máy Ảo TRON (TVM).

Mainet của TRON được phát hành tháng 06/2018, mới đầu TRON được cộng đồng Fomo khá mạnh, hệ sinh thái thời kỳ đầu ra mắt phát triển khá nhưng sau này bắt đầu lắng dần. Cho đến hiện tại hệ sinh thái gần như không thay đổi nhiều, hầu hết thì đều là các ứng dụng của TRON Foundation.

Các sản phẩm của TRON Foundation thực ra không có gì sáng tạo, hầu hết đều được clone từ các sản phẩm nổi tiếng trên Ethereum và chỉnh sửa lại 1 chút:

  • TVM trên TRON gần giống EVM của Ethereum
  • TRON IDE, một công cụ triển khai Smart Contract giống với Remix
  • Sunswap V1 trên TRON giống với Uniswap V1
  • Sunswap V2 trên TRON giống với Uniswap V2
  • PSM trên TRON giống với PSM của MakerDao
  • 2Pool trên TRON giống pool trên Curve Finance

Trước đây phí trên TRON khá rẻ nhưng đến hiện tại 10/2022 thì phí swap tầm 1.4$, phí này khá cao, cao hơn khá nhiều so với trên BSC. Để tiết kiệm phí các Bot giao dịch thường sử dụng Energy. Để có Energy bạn phải stake TRX hoăc mua trên Token Goodies.

Chuẩn bị trước khi lập trình Smart Contract trên TRON

Cài đặt ví TronLink

Đầu tiên bạn cần phải cài đặt ví TronLink, bạn nên cài đặt extension trên Web để tiện cho việc lập trình và triển khai Smart Contract.

Sau khi cài đặt xong hãy tạo 1 ví mới để bắt đầu, sau đó bạn chuyển sang mạng Testnet (Shasta hoặc Nile) => Mình hay sử dụng Nile để test. Tiếp theo vào link sau để claim TRX và một số token phục vụ cho việc Test: https://nileex.io/join/getJoinPage

Tìm hiểu và sử dụng TRON IDE

Với một người mới, và với Smart Contract không quá phức tạp thì sử dụng TRON IDE là tiện và đơn giản nhất. Bạn xem qua giao diện, các sử dụng nó build, triển khai và gọi hàm. Cách dùng hoàn toàn giống với Remix.

Nếu chưa quen bạn có thể search Google thêm để tìm hiểu về công cụ này.

4 chuẩn token trên TRON blockchain

Hiện TRON có 3 chuẩn token như sau (Chi tiết xem: Token Standards Overview):

  • TRX: Là đơn vị tiền tệ chính thức trên mạng TRON. TRX có thể sử dụng để bỏ phiếu, hay stake để lấy Bandwidth và Energy.
  • Token TRC10: Một tiêu chuẩn mã thông báo kỹ thuật được hỗ trợ bởi chuỗi khối TRON nguyên bản không có Máy ảo TRON (TVM)
    • Ban đầu TRC10 khá phổ biến do nó rất dễ sử dụng, bạn không cần code cũng có thể phát hành được token TRC10 trên TRON.
    • Mọi tài khoản đều có thể phát hành token TRC10 với chi phí 1024 TRX
    • Nhưng TRC10 không thể tăng nguồn cung mà chỉ có thể đốt bớt token thôi.
    • Giao dịch TRC10 chỉ tiêu thụ Bandwidth
  • Token TRC20: Một tiêu chuẩn kỹ thuật được sử dụng cho các hợp đồng thông minh trên chuỗi khối TRON để triển khai mã thông báo với Máy ảo TRON (TVM). Nó hoàn toàn tương thích với ERC‌-20.
    • Gần đây TRC20 phổ biến hơn do hầu hết các DApp đều sử dụng TRC20. Ví dụ: BTT trước đây (BTT-OLD) sử dụng token TRC10, sau này đã chuyển sang token theo chuẩn TRC20 (BTT).
    • TRC20 tiêu thụ cả Bandwidth và Energy.
  • TRC721: Chuẩn cho các NFT trên mạng TRON, hoàn toàn tương thích với ERC-721 trên Ethereum.

Hiểu về khái niệm Energy và Bandwidth

Hiểu về Energy và Bandwidth

Đây là hai khái niệm khá mới trên TRON mà trên Ethereum không có. Chi tiết giải thích bạn xem bài viết: TRON bandwidth and energy explained. Mình xin nói lại một cách đơn giản dễ hiểu hơn.

Khi thực hiện một giao dịch trên TRON Network bạn cần phải trả phí cho nó, trên TRON sẽ thu phí này thông qua BandwidthEnergy:

  • Bandwidth: Tài nguyên giúp bạn thực hiện các giao dịch trên TRON, với mỗi giao dịch hệ thống sẽ tự động trừ Bandwidth của bạn.
    • Mỗi giao dịch sẽ tiêu tốn một lượng Bandwidth khác nhau, hệ thống sẽ tự động trừ lượng Bandwidth khác nhau. Trường hợp tài khoản không đủ Bandwidth, hệ thống sẽ tự động đốt TRX để bù lượng Bandwidth bị thiếu với tỉ giá quy đổi: 1 TRX = 1000 Bandwith
    • Mỗi ví đã được kích hoạt hàng ngày sẽ được cấp 1500 Bandwidth để sử dụng, bạn xem thông tin này trên Tron Explorer, ví dụ: TMzqLUTWMeqgGmPZJtZ4ReivxWngvPsFVS
    • Thao tác chuyển TRX và token TRC10 không phải tương tác với Smart Contract nên chỉ sử dụng Bandwidth,mỗi giao dịch transfer sẽ tiêu tốn dưới 500 Bandwidth, lượng Bandwidth thay đổi tùy vào ví nhận đã được kích hoạt hay chưa, nếu chưa được kích hoạt sẽ cần lượng nhiều hơn. Như vậy lượng bandwidth được cấp hàng ngày bạn có thể thực hiện được trên 3 giao dịch chuyển TRX hoặc token TRC10.
  • Energy: Đây là tài nguyên đặc biệt được sử dụng để để xử lý các hợp đồng thông trên mạng TRON.
    • Như vậy các giao dịch tới các Smart Contract sẽ phải sử dụng cả Bandwidth và Energy. Việc chuyển token TRC20 yêu cầu phải thao tác Smart Contract nên phải sử dụng cả hai tài nguyên Bandwidth và Energy.
    • Tùy thuộc từng giao dịch gọi smart contract mà lượng energy tiêu thụ sẽ khác nhau, nhưng nói chung khá tốn. Nếu hết energy hệ thống sẽ tự động đốt TRX để bù lượng energy bị thiếu với tỉ lệ quy đổi là: 1 TRX = 3571.42857 Energy. Đây ví dụ giao dịch đốt TRX để bù Energy: 1c44f204ce04a359a3aff7c28eadee47cd23d16381380519b941ac267d42f201

Stake TRX để nhận Energy/Bandwidth

Như vậy mỗi giao dịch trên TRON, bạn cần phải có Bandwidth và Energy làm phí, nếu không có phải trả lượng TRX tương đương. Trước đây phí trên TRON khá rẻ, nhưng gần đây phí giao dịch trên TRON khá đắt nên bạn cần quan tâm tới nó.

Vậy có cách nào để có Bandwidth và Energy mà bạn không cần phải đốt TRX không? Câu trả lời là có, bạn phải stake TRX để đổi lấy Bandwidth hoặc Energy:

  • Mỗi lần stake bạn chỉ đổi lấy Energy hoặc Bandwith. Ví A có thể stake để lấy bandwitdth cho ví B. Với energy có được thông qua Stake, mỗi khi Energy được sử dụng, sau một thời gian Energy sẽ được hồi dần.
  • Sau khi Stake, ngoài nhận được Energy hoặc Bandwidth, bạn còn nhận được TRON Power, bạn sử dụng cái này để vote cho các node để nhận thêm phần thưởng TRX do node trả cho bạn. Link để vote: https://tronscan.org/#/sr/votes
  • Sau khi stake bạn cần phải chờ tối thiểu 3 ngày mới được unstake.
  • Để stake bạn vào link sau https://tronscan.org/#/wallet/resources và kết nối tới ví TronLink, sau đó kích nút Obtain. Tỉ giá quy đổi khi stake như sau (Tham khảo trên trang (ENERGY/BANDWIDTH CALCULATORS):
    • 1 TRX = 27.75472 Energy
    • 1 TRX = 1.06005 Bandwidth
  • Giả sử mỗi giao dịch swap tiêu thụ tầm 79000 Energy (Tham khảo giao dịch: e03bb5cf81a6e94be8cb3c30506755bd607db252b768f6829e2202aae343afa9), bot của bạn mà giao dịch tầm 100 giao dịch / ngày thì bạn cần phải stake ~284636 TRX (~17817$) => Một lượng tài sản không hề nhỏ.
Kích nút Obtain để stake TRX
Kích nút Obtain để stake TRX
Giao diện để stake TRX
Giao diện để stake TRX

Mua Energy/Bandwidth

Nếu bạn muốn giao dịch rẻ, nhưng bạn không có quá nhiều TRX để stake thì bạn phải làm sao? Có một giải pháp đó là mua Energy và Bandwidth trên trang Token Goodies. Thực chất là bạn bỏ tiền thuê một người đang giữ TRX stake để cung cấp energy/bandwidth cho mình.

Với cách này bạn tiết kiệm được 62% chi phí, giá cả thay đổi tùy từng thời điểm.

Một số kiến thức cơ bản trước khi lập trình Smart Contract

Smart Contract trên TRON viết bằng Solidity, nên các bạn phải biết sơ sơ về ngôn ngữ này. Bạn có thể tham khảo tại: Solidity TutorialSolidityLang. Và bạn xem OpenZeppelin, một thư viện smart contract được sử dụng nhiều nhất hiện nay.

Các thành phần của một Smart Contract

Gồm 2 thành phần chính là DataFunction. Ngoài ra còn có Event and Log.

Data

Mọi dữ liệu Smart Contract phải được gán cho một vị trí: Storage hoặc Memory. Sẽ rất tốn kém khi sửa đổi dữ liệu Storage, vì vậy bạn cần cân nhắc nơi dữ liệu của mình sẽ được lưu trữ một cách khôn ngoan.

* Storage: Dữ liệu lưu trữ lâu dài sẽ được lưu trong Storage và được biểu thị như các biến trạng thái. Các giá trị này được lưu trữ vĩnh viễn trên blockchain. Biến lưu trong Storage được khai báo như sau:

contract SimpleStorage {
    uint storedData; // State variable
    // ...
}

Các kiểu dữ liệu hỗ trợ gồm: address, boolean, integer, fixed point numbers, fixed-size byte arrays, dynamically-sized byte arrays, Rational and integer literals, String literals, Hexadecimal literals, Enums

Bạn chú ý rằng dữ liệu address trên Smart Contract theo định dạng Hexa, chứ không phải địa chỉ bình thường bạn hay sử dụng, địa chỉ TRON bình thường bạn hay nhìn thấy theo chuẩn Base58. Ví dụ tài khoản TA9h822trLafTtsGXQc4g4ehPvyNzkQNsS thì địa chỉ ở dạng Hexa là 4101fba20cb405734c6b2e704b9ed67c0b5ea74d9e => Khi đó trong Smart Contract bạn phải bỏ kí tự 41 ở đầu đi (41 tương ứng tiền tố T):

address newAddress = 0x01fbA20CB405734C6B2e704B9eD67C0b5ea74D9E

* Memory: Các giá trị chỉ được lưu trữ trong suốt thời gian thực thi của một hàm được gọi là các biến Memory. Vì chúng không được lưu trữ vĩnh viễn trên blockchain nên chúng rẻ hơn nhiều khi sử dụng.

* Biến môi trường: Ngoài ra có nhiều biến toàn cục bạn có thể sử dụng để lấy thông tin về blockchain hoặc giao dịch hiện tại. Một số biến toàn cục hay dùng:

  • block.timestamp: Kiểu uint256, thời gian khối hiện tại tính bằng giây.
  • block.number: Kiểu uint, số block hiện tại
  • block.coinbase: Kiểu address, địa chỉ của node siêu đại diện tạo ra khối hiện tại
  • msg.sender: Kiểu address, Người gửi (Người gọi Smart Contract hiện tại)
  • msg.value: Kiểu uint, số lượng TRX gửi kèm
  • msg.data: Kiểu bytes, chứa toàn bộ dữ liệu gửi
  • msg.sig: Kiểu bytes4, mã định danh hàm gọi.
  • now: Kiểu uint, chính là block.timestamp

Function

Có hai kiểu gọi hàm:

  • internal: Các hàm và biến storage nội bộ chỉ có thể truy cập nội bộ (Tức là từ bên trong hợp đồng hiện tại, hoặc hợp mở rộng từ nó). Các hàm này không thể được gọi từ EVM.
  • external: Các hàm này là một phần của giao diện hợp đồng, chúng được gọi từ các hợp đồng khác hoặc thông qua các giao dịch. Các hàm này cho phép gọi từ EVM. Khi gọi hàm external từ bên trong hợp đồng bạn phải sử dụng thêm với this, chẳng hạn: this.f()

Các hàm cũng có thể là public hoặc private:

  • public: Các hàm public có thể được gọi từ bên trong nội bộ hợp đồng hoặc từ bên ngoài thông qua message.
  • private: Chỉ gọi từ bên trong nội bộ hợp đồng

Dưới đây là ví dụ hàm public:

function update_name(string memory value) public {
    dapp_name = value;
}

Chúng ta cần phân biệt thêm 2 loại Function: View/Pure/Payable function, ConstructorBuilt-in function:

  • View function: Không cho phép thay đổi trang thái của dữ liệu hợp đồng. Hàm truy vấn balance là một ví dụ:
    function balanceOf(address _owner) public view returns (uint256 _balance) {
    return ownerPizzaCount[_owner];
    }
  • Pure function:
  • Payable function:
  • Constructor function: Chỉ được thực thi 1 lần khi hợp đồng được triển khai lần đầu tiên. Hàm này thường dùng để khởi tạo các biến trạng thái.
    constructor() public {
    owner = msg.sender;
    }
  • Built-in function: Đây là các hàm được tích hợp sẵn, như hàm address.send() để gửi TRX sang tài khoản khác.

Nhưng thao tác sau sẽ làm thay đổi trang thái của Smart Contract:

  • Thay đổi giá trị các biến trạng thái
  • Phát sự kiện
  • Tạo một contract khác
  • Sử dụng selfdestruct
  • Gửi TRX
  • Gọi các hàm không được đánh dấu là view hoặc pure
  • Sending trx via calls.
  • Sử dụng các lời gọi cấp thấp (low-level call)
  • Sử dụng mã nhúng assembly

Các thành phần của một function gồm:

  • Từ khóa function
  • Tên function
  • Danh sách tham số và kiểu dữ liệu tương ứng
  • Kiểu truy cập: public/private/internal/external
  • Đánh dấu hàm nếu có: pure/view/payable
  • Kiểu dữ liệu trả về nếu có

Dưới đây là một contract mẫu:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.6.0;

contract ExampleDapp {
    string dapp_name; // state variable

    // Called when the contract is deployed and initializes the value
    constructor() public {
        dapp_name = "My Example dapp";
    }

    // Get Function
    function read_name() public view returns(string memory) {
        return dapp_name;
    }

    // Set Function
    function update_name(string memory value) public {
        dapp_name = value;
    }
}

Event and Log

Event cho phép chúng ta dễ dàng truy vấn “những điều” đã xảy ra khi một giao dịch hợp đồng được thực hiện.

Log được sử dụng để “ghi” dữ liệu vào cấu trúc dữ liệu bên ngoài hợp đồng thông minh. Thông tin Log không thể được truy cập bởi các hợp đồng thông minh, nhưng có thể cung cấp thông tin về các giao dịch và những gì đã xảy ra trong các khối.

Khi một giao dịch hợp đồng được thực hiện thành công, hợp đồng thông minh có thể phát ra các Event và ghi Log vào blockchain.

Smart Contract Library

Bạn không cần phải viết mọi hợp đồng thông minh trong dự án của mình từ đầu. Có rất nhiều thư viện hợp đồng thông minh mã nguồn mở có sẵn cung cấp các khối xây dựng có thể tái sử dụng cho dự án của bạn có thể giúp bạn không phải phát minh lại bánh xe.

OpenZeppelin Contracts là thư viện rất nổi tiếng và được rất nhiều Dev trên toàn thế giới sử dụng. Các contract hay dùng như:

Lập trình Smart Contract trên TRON

Để đơn giản cho việc code và triển khai Smart Contract, chúng ta sẽ sử dụng TronIDE, còn bạn nào muốn tạo Smart Contract phức tạp thì có thể sử dụng TronBox.

Ở đây chúng ta học thông qua việc xây dựng các Smart Contract cụ thể với các nghiệp vụ hay được sử dụng trong thực tế.

Smart Contract để lấy thông tin tài sản, chuyển và nhận tài sản

Dưới đây là contract sẽ có các hàm để:

  • Lấy thông tin tài sản: Gồm có TRX, TRC10 và TRC20. Có 3 hàm tương ứng:
    getTrxBalance()
    getTrc10Balance()
    getTrc20Balance()
  • Hỗ trợ chuyển tiền tới contract: Với token TRC20 bạn có thể chuyển thoái mái tới contract nhưng với TRX và token TRC10, bạn muốn contract của mình nhận được tiền bạn phải khải báo hàm sau (Ko cần cài đặt gì cả):
    receive() external payable { }
  • Rút tiền ra khỏi contract: Để hỗ trợ rút tiền ra khỏi contract, bạn bắt buộc phải cài đặt thêm hàm để làm việc này. Ba hàm dưới được cài đặt để hỗ trợ rút TRX, TRC10 và TRC20 ra khỏi contract:
    withdraw()
    withdrawTokenTrc10()
    withdrawTokenTrc20()

Toàn bộ mã nguồn của Contract như sau:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.6;

interface ITRC20 {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint value) external returns (bool);
}

contract TronBalance  {
    address public owner;
    
    modifier onlyOwner() {
        require(msg.sender == owner, 'Only the owner can perform this action');
        _;
    }

    constructor() {
        owner = msg.sender;
    }
    
    // Allow send TRX, TRC10 token to this contract
    receive() external payable {
    }

    // Get balance of TRX
    function getTrxBalance(address account) external view returns (uint256) {
        return account.balance;
    }
    
    // Get balance of TRC10 token
    function getTrc10Balance(address account, uint256 tokenId) external view returns (uint256) {
        return account.tokenBalance(trcToken(tokenId));
    }

    // Get balance of TRC20 token
    function getTrc20Balance(address account, address token) external view returns (uint256) {
        return ITRC20(token).balanceOf(account);
    }
    
    // Withdraw TRX to the an account
    function withdraw(address payable to, uint amount) public onlyOwner {
        to.transfer(amount);
    }

    // Witdraw token TRC10
    function withdrawTokenTrc10(address payable to, uint256 tokenId, uint256 amount) public onlyOwner {
        to.transferToken(amount, trcToken(tokenId));
    }
    
    // Witdraw token TRC20
    function withdrawTokenTrc20(address to, address tokenAddr, uint256 amount) public onlyOwner {
        ITRC20(tokenAddr).transfer(to, amount);
    }
}

Một số chú ý khi lập trình với Smart Contract trên TRON

So sánh xâu (String compare)

Trên smart contract không hỗ trợ so sánh hai xâu trực tiếp. Ví dụ:

// Không hỗ trợ
require(tokenSymbol=="USDT", "The token is not supported!");

Nếu bạn muốn so sánh xâu thì bạn cần cài đặt thêm hàm:

// Cài đặt hàm so sánh string
function _compareString(string memory a, string memory b) private pure returns (bool) {
    return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));
}

...
require(_compareString(tokenSymbol, "USDT"), "The token is not supported!");
...

Tài liệu tham khảo:

Bài viết này có hữu ích với bạn?

Kích vào một biểu tượng ngôi sao để đánh giá bài viết!

Xếp hạng trung bình 0 / 5. Số phiếu: 0

Bài viết chưa có đánh giá! Hãy là người đầu tiên đánh giá bài viết này.

Trả lời

Giao diện bởi Anders Norén