Harmony được giới thiệu là một nển tảng blockchain nhanh và bảo mật cho các ứng dụng phân tán. Mainnet của họ có 1000 nodes được chia thành 4 shards và với khả năng đóng blocks trong 8s. Nền tảng blockchain này giống Ethereum đến lạ kỳ, có chăng cái khác hiện tại của nó là đang sử dụng một cơ chế đồng thuận khác đó là Effective Proof-of-Stake (EPoS), theo như nhà phát triển thì đây là một loại cải tiến của PoS. Trong rất nhiều sự tương đồng với Ethereum thì một trong số đó là đều có smart contract, cũng sử dụng solidity để viết contract và deploy cũng có thể dùng những công cụ phát triển của Ethereum. Để chứng minh cho điều này mình xin viết bài này hướng dẫn các bạn deploy một smart contract lên mạng Harmony
Yêu cầu cài đặt
Cũng có thể sử dụng Truffle để code và deploy smart contract nên ở đâu chúng ta cần install Truffle
1 2 | <span class="token function">npm</span> <span class="token function">install</span> -g <a class="__cf_email__" href="/cdn-cgi/l/email-protection">[email protected]</a> |
Khởi tạo project
1 2 3 4 | <span class="token function">mkdir</span> harmonyERC20 <span class="token builtin class-name">cd</span> harmonyERC20 truffle init |
Installing Harmony Core
Để deploy ta cần install Harmony @harmony-js/core
1 2 3 | <span class="token function">npm</span> <span class="token function">install</span> --save @harmony-js/<a class="__cf_email__" href="/cdn-cgi/l/email-protection">[email protected]</a> <span class="token function">npm</span> <span class="token function">install</span> --save tslib |
Install thư viện bổ xung
Nếu contract phát triển trên chuẩn ERC-20 hoặc ERC-721 thì bạn cần install thêm các thư viện của open zeppelin libraries.
1 2 3 | <span class="token function">npm</span> <span class="token function">install</span> openzeppelin-solidity -s <span class="token function">npm</span> <span class="token function">install</span> --save dotenv |
Tạo một file package.json
Cần tạo một file package.json như sau để tải các thư viện:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token punctuation">{</span> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"harmony-erc20"</span><span class="token punctuation">,</span> <span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"1.0.0"</span><span class="token punctuation">,</span> <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Harmony sample ERC20 deploy"</span><span class="token punctuation">,</span> <span class="token property">"main"</span><span class="token operator">:</span> <span class="token string">"truffle.js"</span><span class="token punctuation">,</span> <span class="token property">"dependencies"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"@harmony-js/core"</span><span class="token operator">:</span> <span class="token string">"^0.1.22"</span><span class="token punctuation">,</span> <span class="token property">"dotenv"</span><span class="token operator">:</span> <span class="token string">"^8.2.0"</span><span class="token punctuation">,</span> <span class="token property">"tslib"</span><span class="token operator">:</span> <span class="token string">"^1.10.0"</span><span class="token punctuation">,</span> <span class="token property">"openzeppelin-solidity"</span><span class="token operator">:</span> <span class="token string">"^2.2.0"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Sau đó chạy command: npm install
Configure truffle để sử dụng được Harmony
Để build được contract trên Harmony ta cần sử đổi file truffle-config.js, để setup network thành Harmony network.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'dotenv'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">config</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> TruffleProvider <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@harmony-js/core'</span><span class="token punctuation">)</span> <span class="token comment">//Local</span> <span class="token keyword">const</span> local_mnemonic <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">LOCAL_MNEMONIC</span> <span class="token keyword">const</span> local_private_key <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">LOCAL_PRIVATE_KEY</span> <span class="token keyword">const</span> local_url <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">LOCAL_0_URL</span><span class="token punctuation">;</span> <span class="token comment">//Testnet</span> <span class="token keyword">const</span> testnet_mnemonic <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">TESTNET_MNEMONIC</span> <span class="token keyword">const</span> testnet_private_key <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">TESTNET_PRIVATE_KEY</span> <span class="token keyword">const</span> testnet_url <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">TESTNET_0_URL</span> <span class="token comment">//Mainnet</span> <span class="token keyword">const</span> mainnet_mnemonic <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">MAINNET_MNEMONIC</span> <span class="token keyword">const</span> mainnet_private_key <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">MAINNET_PRIVATE_KEY</span> <span class="token keyword">const</span> mainnet_url <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">MAINNET_0_URL</span><span class="token punctuation">;</span> <span class="token comment">//GAS - Currently using same GAS accross all environments</span> gasLimit <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">GAS_LIMIT</span> gasPrice <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">GAS_PRICE</span> module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span> networks<span class="token operator">:</span> <span class="token punctuation">{</span> local<span class="token operator">:</span> <span class="token punctuation">{</span> network_id<span class="token operator">:</span> <span class="token string">'2'</span><span class="token punctuation">,</span> <span class="token comment">// Any network (default: none)</span> <span class="token function-variable function">provider</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> truffleProvider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TruffleProvider</span><span class="token punctuation">(</span> local_url<span class="token punctuation">,</span> <span class="token punctuation">{</span> memonic<span class="token operator">:</span> local_mnemonic <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> shardID<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span> chainId<span class="token operator">:</span> <span class="token number">2</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> gasLimit<span class="token operator">:</span> gasLimit<span class="token punctuation">,</span> gasPrice<span class="token operator">:</span> gasPrice<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> newAcc <span class="token operator">=</span> truffleProvider<span class="token punctuation">.</span><span class="token function">addByPrivateKey</span><span class="token punctuation">(</span>local_private_key<span class="token punctuation">)</span><span class="token punctuation">;</span> truffleProvider<span class="token punctuation">.</span><span class="token function">setSigner</span><span class="token punctuation">(</span>newAcc<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> truffleProvider<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> testnet<span class="token operator">:</span> <span class="token punctuation">{</span> network_id<span class="token operator">:</span> <span class="token string">'2'</span><span class="token punctuation">,</span> <span class="token comment">// Any network (default: none)</span> <span class="token function-variable function">provider</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> truffleProvider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TruffleProvider</span><span class="token punctuation">(</span> testnet_url<span class="token punctuation">,</span> <span class="token punctuation">{</span> memonic<span class="token operator">:</span> testnet_mnemonic <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> shardID<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span> chainId<span class="token operator">:</span> <span class="token number">2</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> gasLimit<span class="token operator">:</span> gasLimit<span class="token punctuation">,</span> gasPrice<span class="token operator">:</span> gasPrice<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> newAcc <span class="token operator">=</span> truffleProvider<span class="token punctuation">.</span><span class="token function">addByPrivateKey</span><span class="token punctuation">(</span>testnet_private_key<span class="token punctuation">)</span><span class="token punctuation">;</span> truffleProvider<span class="token punctuation">.</span><span class="token function">setSigner</span><span class="token punctuation">(</span>newAcc<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> truffleProvider<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> mainnet0<span class="token operator">:</span> <span class="token punctuation">{</span> network_id<span class="token operator">:</span> <span class="token string">'1'</span><span class="token punctuation">,</span> <span class="token comment">// Any network (default: none)</span> <span class="token function-variable function">provider</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> truffleProvider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TruffleProvider</span><span class="token punctuation">(</span> mainnet_url<span class="token punctuation">,</span> <span class="token punctuation">{</span> memonic<span class="token operator">:</span> mainnet_mnemonic <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> shardID<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span> chainId<span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> gasLimit<span class="token operator">:</span> gasLimit<span class="token punctuation">,</span> gasPrice<span class="token operator">:</span> gasPrice <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> newAcc <span class="token operator">=</span> truffleProvider<span class="token punctuation">.</span><span class="token function">addByPrivateKey</span><span class="token punctuation">(</span>mainnet_private_key<span class="token punctuation">)</span><span class="token punctuation">;</span> truffleProvider<span class="token punctuation">.</span><span class="token function">setSigner</span><span class="token punctuation">(</span>newAcc<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> truffleProvider<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token comment">// Set default mocha options here, use special reporters etc.</span> mocha<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token comment">// timeout: 100000</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token comment">// Configure your compilers</span> compilers<span class="token operator">:</span> <span class="token punctuation">{</span> solc<span class="token operator">:</span> <span class="token punctuation">{</span> version<span class="token operator">:</span> <span class="token string">"0.5.8"</span><span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Trong này sẽ có một số chỗ sử dụng đến các biến môi trường nên ta cũng cần setup file .env như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token comment">//LOCAL</span> <span class="token comment">//Local uses account one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7 on Shard 0</span> <span class="token constant">LOCAL_PRIVATE_KEY</span><span class="token operator">=</span><span class="token string">'45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e'</span> <span class="token constant">LOCAL_MNEMONIC</span><span class="token operator">=</span><span class="token string">'urge clog right example dish drill card maximum mix bachelor section select'</span> <span class="token constant">LOCAL_0_URL</span><span class="token operator">=</span><span class="token string">'http://localhost:9500'</span> <span class="token comment">//TESTNET</span> <span class="token comment">//Account: one18t4yj4fuutj83uwqckkvxp9gfa0568uc48ggj7</span> <span class="token constant">TESTNET_PRIVATE_KEY</span><span class="token operator">=</span><span class="token string">'01F903CE0C960FF3A9E68E80FF5FFC344358D80CE1C221C3F9711AF07F83A3BD'</span> <span class="token constant">TESTNET_MNEMONIC</span><span class="token operator">=</span><span class="token string">'urge clog right example dish drill card maximum mix bachelor section select'</span> <span class="token constant">TESTNET_0_URL</span><span class="token operator">=</span><span class="token string">'https://api.s0.b.hmny.io'</span> <span class="token constant">TESTNET_1_URL</span><span class="token operator">=</span><span class="token string">'https://api.s1.b.hmny.io'</span> <span class="token comment">//MAINNET</span> <span class="token comment">//Please replace MAINNET_PRIVATE_KEY and MAINNET_MNEMONIC with your own!</span> <span class="token comment">//Account: one18t4yj4fuutj83uwqckkvxp9gfa0568uc48ggj7</span> <span class="token constant">MAINNET_PRIVATE_KEY</span><span class="token operator">=</span><span class="token string">'01F903CE0C960FF3A9E68E80FF5FFC344358D80CE1C221C3F9711AF07F83A3BD'</span> <span class="token constant">MAINNET_MNEMONIC</span><span class="token operator">=</span><span class="token string">'urge clog right example dish drill card maximum mix bachelor section select'</span> <span class="token constant">MAINNET_0_URL</span><span class="token operator">=</span><span class="token string">'https://api.s0.t.hmny.io'</span> <span class="token constant">GAS_LIMIT</span><span class="token operator">=</span><span class="token number">3321900</span> <span class="token constant">GAS_PRICE</span><span class="token operator">=</span><span class="token number">1000000000</span> |
Viết smart contract
Chúng ta sẽ viết 2 file triển khai trên Harmony HRC20 như dưới đây:
- HarmonyMintable.sol123456789101112131415pragma solidity <span class="token operator">>=</span><span class="token number">0.4</span><span class="token number">.21</span> <span class="token operator"><</span><span class="token number">0.6</span><span class="token number">.0</span><span class="token punctuation">;</span><span class="token keyword">import</span> <span class="token string">"openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol"</span><span class="token punctuation">;</span><span class="token keyword">import</span> <span class="token string">"openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"</span><span class="token punctuation">;</span><span class="token keyword">import</span> <span class="token string">"openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"</span><span class="token punctuation">;</span>contract HarmonyERC20 is <span class="token constant">ERC20</span><span class="token punctuation">,</span> ERC20Detailed<span class="token punctuation">,</span> ERC20Mintable <span class="token punctuation">{</span><span class="token function">constructor</span><span class="token punctuation">(</span>string memory _name<span class="token punctuation">,</span> string memory _symbols<span class="token punctuation">,</span> uint8 _decimals<span class="token punctuation">,</span> uint256 _amount<span class="token punctuation">)</span><span class="token function">ERC20Detailed</span><span class="token punctuation">(</span>_name<span class="token punctuation">,</span> _symbols<span class="token punctuation">,</span> _decimals<span class="token punctuation">)</span><span class="token keyword">public</span> <span class="token punctuation">{</span><span class="token function">_mint</span><span class="token punctuation">(</span>msg<span class="token punctuation">.</span>sender<span class="token punctuation">,</span> _amount<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
- HarmonyERC20.sol1234567891011121314pragma solidity <span class="token operator">>=</span><span class="token number">0.4</span><span class="token number">.21</span> <span class="token operator"><</span><span class="token number">0.6</span><span class="token number">.0</span><span class="token punctuation">;</span><span class="token keyword">import</span> <span class="token string">"openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol"</span><span class="token punctuation">;</span><span class="token keyword">import</span> <span class="token string">"openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"</span><span class="token punctuation">;</span>contract HarmonyERC20 is <span class="token constant">ERC20</span><span class="token punctuation">,</span> ERC20Detailed <span class="token punctuation">{</span><span class="token function">constructor</span><span class="token punctuation">(</span>string memory _name<span class="token punctuation">,</span> string memory _symbols<span class="token punctuation">,</span> uint8 _decimals<span class="token punctuation">,</span> uint256 _amount<span class="token punctuation">)</span><span class="token function">ERC20Detailed</span><span class="token punctuation">(</span>_name<span class="token punctuation">,</span> _symbols<span class="token punctuation">,</span> _decimals<span class="token punctuation">)</span><span class="token keyword">public</span> <span class="token punctuation">{</span><span class="token function">_mint</span><span class="token punctuation">(</span>msg<span class="token punctuation">.</span>sender<span class="token punctuation">,</span> _amount<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
Add file migration
cuối cùng là file migration để deploy contract:
- 2_deploy_HarmonyERC20.js12345678910111213141516<span class="token keyword">var</span> HarmonyERC20 <span class="token operator">=</span> artifacts<span class="token punctuation">.</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"HarmonyERC20"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">deployer<span class="token punctuation">,</span> network<span class="token punctuation">,</span> accounts</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">const</span> name <span class="token operator">=</span> <span class="token string">"HarmonyERC20"</span><span class="token keyword">const</span> symbol <span class="token operator">=</span> <span class="token string">"H20"</span><span class="token keyword">const</span> decimals <span class="token operator">=</span> <span class="token number">18</span><span class="token keyword">const</span> amount <span class="token operator">=</span> <span class="token number">1000000</span><span class="token keyword">const</span> tokens <span class="token operator">=</span> web3<span class="token punctuation">.</span>utils<span class="token punctuation">.</span><span class="token function">toWei</span><span class="token punctuation">(</span>amount<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'ether'</span><span class="token punctuation">)</span>deployer<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> deployer<span class="token punctuation">.</span><span class="token function">deploy</span><span class="token punctuation">(</span>HarmonyERC20<span class="token punctuation">,</span> name<span class="token punctuation">,</span> symbol<span class="token punctuation">,</span> decimals<span class="token punctuation">,</span> tokens<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
Cấu trúc thư mục sẽ như sau:
Compile và deploy contracts
Sử dụng các câu lệnh sau để compile và deploy:
1 2 3 4 | truffle compile truffle migrate --network testnet --reset truffle networks |
Kết quả sẽ như sau
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | <a class="__cf_email__" href="/cdn-cgi/l/email-protection">[email protected]</a> MINGW64 ~/Downloads/harmonyERC20 $ truffle migrate --network testnet --reset Compiling your contracts<span class="token punctuation">..</span>. <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span> <span class="token operator">></span> Compiling .contractsHarmonyERC20.sol <span class="token operator">></span> Compiling .contractsHarmonyMintable.sol <span class="token operator">></span> Compiling .contractsMigrations.sol <span class="token operator">></span> Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20.sol <span class="token operator">></span> Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol <span class="token operator">></span> Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol <span class="token operator">></span> Compiling openzeppelin-soliditycontractsGSNContext.sol <span class="token operator">></span> Compiling openzeppelin-soliditycontractsaccessRoles.sol <span class="token operator">></span> Compiling openzeppelin-soliditycontractsaccessrolesMinterRole.sol <span class="token operator">></span> Compiling openzeppelin-soliditycontractsmathSafeMath.sol <span class="token operator">></span> Compiling openzeppelin-soliditycontractstokenERC20ERC20.sol <span class="token operator">></span> Compiling openzeppelin-soliditycontractstokenERC20IERC20.sol <span class="token operator">></span> Artifacts written to C:UsersngovaDownloadsharmonyERC20buildcontracts <span class="token operator">></span> Compiled successfully using: - solc: <span class="token number">0.5</span>.8+commit.23d335f2.Emscripten.clang Migrations dry-run <span class="token punctuation">(</span>simulation<span class="token punctuation">)</span> <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span> <span class="token operator">></span> Network name: <span class="token string">'testnet-fork'</span> <span class="token operator">></span> Network id: <span class="token number">2</span> <span class="token operator">></span> Block gas limit: <span class="token number">3321900</span> <span class="token punctuation">(</span>0x32b02c<span class="token punctuation">)</span> 1_initial_migration.js <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span> Replacing <span class="token string">'Migrations'</span> ---------------------- <span class="token operator">></span> block number: <span class="token number">922490</span> <span class="token operator">></span> block timestamp: <span class="token number">1597312204</span> <span class="token operator">></span> account: 0x3aea49553Ce2E478f1c0c5ACC304a84F5F4d1f98 <span class="token operator">></span> balance: <span class="token number">3553833.469779825581597178</span> <span class="token operator">></span> gas used: <span class="token number">147243</span> <span class="token punctuation">(</span>0x23f2b<span class="token punctuation">)</span> <span class="token operator">></span> gas price: <span class="token number">2</span> gwei <span class="token operator">></span> value sent: <span class="token number">0</span> ETH <span class="token operator">></span> total cost: <span class="token number">0.000294486</span> ETH ------------------------------------- <span class="token operator">></span> Total cost: <span class="token number">0.000294486</span> ETH 2_deploy_HarmonyERC20.js <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span> Replacing <span class="token string">'HarmonyERC20'</span> ------------------------ <span class="token operator">></span> block number: <span class="token number">922492</span> <span class="token operator">></span> block timestamp: <span class="token number">1597312282</span> <span class="token operator">></span> account: 0x3aea49553Ce2E478f1c0c5ACC304a84F5F4d1f98 <span class="token operator">></span> balance: <span class="token number">3553833.466765935581597178</span> <span class="token operator">></span> gas used: <span class="token number">1479604</span> <span class="token punctuation">(</span>0x1693b4<span class="token punctuation">)</span> <span class="token operator">></span> gas price: <span class="token number">2</span> gwei <span class="token operator">></span> value sent: <span class="token number">0</span> ETH <span class="token operator">></span> total cost: <span class="token number">0.002959208</span> ETH ------------------------------------- <span class="token operator">></span> Total cost: <span class="token number">0.002959208</span> ETH Summary <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span> <span class="token operator">></span> Total deployments: <span class="token number">2</span> <span class="token operator">></span> Final cost: <span class="token number">0.003253694</span> ETH Starting migrations<span class="token punctuation">..</span>. <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span> <span class="token operator">></span> Network name: <span class="token string">'testnet'</span> <span class="token operator">></span> Network id: <span class="token number">2</span> <span class="token operator">></span> Block gas limit: <span class="token number">3321900</span> <span class="token punctuation">(</span>0x32b02c<span class="token punctuation">)</span> 1_initial_migration.js <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span> Replacing <span class="token string">'Migrations'</span> ---------------------- <span class="token operator">></span> transaction hash: 0x257590b6584a5c3d75cd468fb233f2d52d0197781ead49ab73db2478777d8383 <span class="token operator">></span> Blocks: <span class="token number">1</span> Seconds: <span class="token number">5</span> <span class="token operator">></span> contract address: 0xD64Bf0346fDbb6Cb2f95Ec8c2c16129A34f92DB6 <span class="token operator">></span> block number: <span class="token number">0</span> <span class="token operator">></span> block timestamp: <span class="token number">1561734000</span> <span class="token operator">></span> account: 0x3aea49553Ce2E478f1c0c5ACC304a84F5F4d1f98 <span class="token operator">></span> balance: <span class="token number">3553833.469888176581597178</span> <span class="token operator">></span> gas used: <span class="token number">186135</span> <span class="token punctuation">(</span>0x2d717<span class="token punctuation">)</span> <span class="token operator">></span> gas price: <span class="token number">1</span> gwei <span class="token operator">></span> value sent: <span class="token number">0</span> ETH <span class="token operator">></span> total cost: <span class="token number">0.000186135</span> ETH <span class="token operator">></span> Saving migration to chain. <span class="token operator">></span> Saving artifacts ------------------------------------- <span class="token operator">></span> Total cost: <span class="token number">0.000186135</span> ETH 2_deploy_HarmonyERC20.js <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span> Replacing <span class="token string">'HarmonyERC20'</span> ------------------------ <span class="token operator">></span> transaction hash: 0x64891c54b2143ed696d3fa1cbafd8a8092af9d6d86e451c43dc2297332c33449 <span class="token operator">></span> Blocks: <span class="token number">1</span> Seconds: <span class="token number">5</span> <span class="token operator">></span> contract address: 0xc98d647082b2E6A2580355E5D89F080878a07993 <span class="token operator">></span> block number: <span class="token number">0</span> <span class="token operator">></span> block timestamp: <span class="token number">1561734000</span> <span class="token operator">></span> account: 0x3aea49553Ce2E478f1c0c5ACC304a84F5F4d1f98 <span class="token operator">></span> balance: <span class="token number">3553833.467895087581597178</span> <span class="token operator">></span> gas used: <span class="token number">1951088</span> <span class="token punctuation">(</span>0x1dc570<span class="token punctuation">)</span> <span class="token operator">></span> gas price: <span class="token number">1</span> gwei <span class="token operator">></span> value sent: <span class="token number">0</span> ETH <span class="token operator">></span> total cost: <span class="token number">0.001951088</span> ETH <span class="token operator">></span> Saving migration to chain. <span class="token operator">></span> Saving artifacts ------------------------------------- <span class="token operator">></span> Total cost: <span class="token number">0.001951088</span> ETH Summary <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span> <span class="token operator">></span> Total deployments: <span class="token number">2</span> <span class="token operator">></span> Final cost: <span class="token number">0.002137223</span> ETH |
1 2 3 4 5 6 7 8 9 10 11 12 13 | <a class="__cf_email__" href="/cdn-cgi/l/email-protection">[email protected]</a> MINGW64 ~/Downloads/harmonyERC20 $ truffle networks Network: <span class="token builtin class-name">local</span> <span class="token punctuation">(</span>id: <span class="token number">2</span><span class="token punctuation">)</span> No contracts deployed. Network: mainnet0 <span class="token punctuation">(</span>id: <span class="token number">1</span><span class="token punctuation">)</span> No contracts deployed. Network: testnet <span class="token punctuation">(</span>id: <span class="token number">2</span><span class="token punctuation">)</span> HarmonyERC20: 0xc98d647082b2E6A2580355E5D89F080878a07993 Migrations: 0xD64Bf0346fDbb6Cb2f95Ec8c2c16129A34f92DB6 |
Kiểm tra totalSupply
Chúng ta sẽ thử trên 2 môi trường là: môi trường test và môi trường gọi từ client
- Môi trường test
Ta cần tạo một file test Harmony.js trong thư mục
test
1234567891011<span class="token keyword">const</span> HarmonyERC20 <span class="token operator">=</span> artifacts<span class="token punctuation">.</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'HarmonyERC20'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">let</span> instance <span class="token operator">=</span> <span class="token keyword">await</span> HarmonyERC20<span class="token punctuation">.</span><span class="token function">deployed</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">let</span> total <span class="token operator">=</span> <span class="token keyword">await</span> instance<span class="token punctuation">.</span><span class="token function">totalSupply</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'total supply: '</span> <span class="token operator">+</span> total<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">;</span>Sau đó chạy command:
12truffle <span class="token builtin class-name">exec</span> test/Harmony.js --network testnetKết quả
12345$ truffle <span class="token builtin class-name">exec</span> test/Harmony.js --network testnetUsing network <span class="token string">'testnet'</span><span class="token builtin class-name">.</span>total supply: <span class="token number">1000000000000000000000000</span>Mọi người hãy để ý lên file 2_deploy_HarmonyERC20.js thì ta đang config giống như wei của Ethereum là dể
decimal = 18
vàamount=1000000
nên total trả về sẽ là :1000000000000000000000000
( 10^(6+18) )12345678910<span class="token operator">...</span><span class="token keyword">const</span> name <span class="token operator">=</span> <span class="token string">"HarmonyERC20"</span><span class="token keyword">const</span> symbol <span class="token operator">=</span> <span class="token string">"H20"</span><span class="token keyword">const</span> decimals <span class="token operator">=</span> <span class="token number">18</span><span class="token keyword">const</span> amount <span class="token operator">=</span> <span class="token number">1000000</span><span class="token keyword">const</span> tokens <span class="token operator">=</span> web3<span class="token punctuation">.</span>utils<span class="token punctuation">.</span><span class="token function">toWei</span><span class="token punctuation">(</span>amount<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'ether'</span><span class="token punctuation">)</span><span class="token operator">...</span>
- Môi trường client
Cũng giống như môi trường client ta sẽ giả lập 1 file js gọi hàm totalSupply thông qua
instance
của contract. Ta sẽ tạo 1 file có tên Harmony_sdk.js trong thư mục test:12345678910111213141516171819202122<span class="token keyword">const</span> <span class="token punctuation">{</span> Harmony <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@harmony-js/core'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token punctuation">{</span> ChainID<span class="token punctuation">,</span> ChainType <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@harmony-js/utils'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> hmy <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Harmony</span><span class="token punctuation">(</span><span class="token string">'https://api.s0.b.hmny.io'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>chainType<span class="token operator">:</span> ChainType<span class="token punctuation">.</span>Harmony<span class="token punctuation">,</span>chainId<span class="token operator">:</span> ChainID<span class="token punctuation">.</span>HmyTestnet<span class="token punctuation">,</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> contractJson <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../build/contracts/HarmonyERC20.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> contractAddr <span class="token operator">=</span> contractJson<span class="token punctuation">.</span>networks<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">.</span>address<span class="token punctuation">;</span><span class="token keyword">const</span> contract <span class="token operator">=</span> hmy<span class="token punctuation">.</span>contracts<span class="token punctuation">.</span><span class="token function">createContract</span><span class="token punctuation">(</span>contractJson<span class="token punctuation">.</span>abi<span class="token punctuation">,</span> contractAddr<span class="token punctuation">)</span><span class="token punctuation">;</span>contract<span class="token punctuation">.</span>methods<span class="token punctuation">.</span><span class="token function">totalSupply</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">total</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'total supply '</span> <span class="token operator">+</span> total<span class="token punctuation">)</span><span class="token punctuation">;</span>process<span class="token punctuation">.</span><span class="token function">exit</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>Sau đó chạy command:
node test/Harmony_sdk.js
Kết quả
123$ node test/Harmony_sdk.jstotal supply: <span class="token number">1000000000000000000000000</span>Mọi người chú ý giúp mình chỗ này mình đang sử dụng mạng Testnet với Id là
2
. Nên nếu trong trường hợp sử dụng cho Mainnet hoặc Testnet khác thì mọi người có thể thay đổi ở đây để có thể get được đúng địa chỉ nha12<span class="token keyword">const</span> contractAddr <span class="token operator">=</span> contractJson<span class="token punctuation">.</span>networks<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">.</span>address<span class="token punctuation">;</span>
Block exporers
Cũng giống như Ethereum thì Harmony cũng có trang để để block exporers: Mainnet và Testnet
- Như ở đây ta deploy nó lên môi trường testnet nên sẽ vào Testnet để kiểm tra
- Contract đã có trên mạng
- Nhưng chưa có transaction nào
Kết luận
Như vậy là chúng ta đã deploy thành công một smart contract lên mạng Harmony blockchain. Chắc hẳn mọi người bây giờ đang có chút ngờ ngợ, ớ không biết có deploy lên đúng mạng không nhỉ mà cứ như là lên Ethereum thế. Không bạn deploy lên đúng mạng rồi đấy chẳng qua là nó giống Ethereum quá thôi mà. Cảm ơn các bạn đã đón đọc rất vui và hẹn gặp lại cách bạn trong các bài viết tiêp theo.