Web3テクノロジースタック丨EVMを使用してフルスタックdappを構築する方法を教えます

Web3テクノロジースタック丨EVMを使用してフルスタックdappを構築する方法を教えます

React、Ethers.js、Solidity、Hardhat を使用してフルスタック dApp を構築する

このチュートリアルでは、Ethereum 仮想マシン (EVM) を活用して、Ethereum、Polygon、Avalanche、Celo など多数のブロックチェーン ネットワーク上でフルスタック アプリケーションを構築できる Web3 テクノロジー スタックについて学習します。

このプロジェクトのコードはここにあります。このチュートリアルのビデオ コースはここにあります。 web3スタックの定義も参照してください‌

私は最近、Edge & Node に開発者リレーションエンジニアとして入社し、Ethereum でのスマート コントラクト開発に深く取り組んでいます。私は、Solidity を使用してフルスタック dApp を構築するのに最適なスタックを特定しました。

▶︎ クライアントサイドフレームワーク - React

▶︎ Ethereum 開発環境 — Hardhat‌

▶︎ Ethereum ネットワーク クライアント ライブラリ - Ethers.js‌

▶︎ API レイヤー - グラフ プロトコル

しかし、これを学習するときに私が抱えた問題は、これらのそれぞれについて個別にかなり良いドキュメントがあったものの、これらすべてをまとめて、それらが互いにどのように機能するかを理解する方法については何もなかったことです。 scaffold-eth (Ethers、Hardhat、The Graph も含まれています) のような非常に優れたテンプレートがいくつかありますが、始めたばかりの人にとっては多すぎるかもしれません。

最新のリソース、ライブラリ、ツールを使用してフルスタックの Ethereum アプリケーションを構築する方法を示すエンドツーエンドのガイドが必要でした。

私が興味を持っているものは次のとおりです。

  1. Ethereum スマート コントラクトをローカル、テスト、メインネットに作成、デプロイ、テストする方法

  2. ローカル、テスト、本番環境/ネットワークを切り替える方法

  3. React、Vue、Svelte、Angular などのさまざまなフロントエンド環境を使用してコントラクトに接続し、対話する方法

これらすべてを理解するのにしばらく時間を費やし、かなり満足できるスタックを使い始めた後、このスタックに興味があるかもしれない他の人々のためだけでなく、私自身の将来の参考のためにも、このスタックを使用してフルスタックの Ethereum アプリケーションを構築およびテストする方法を書き留めておくのはよいことだと思いました。この記事がその参考資料です。


各パーツ


使用する主なパーツと、それらがスタックにどのように適合するかを確認しましょう。

1. イーサリアム開発環境

スマート コントラクトを構築する場合、ライブ環境を扱わずにコントラクトをデプロイし、テストを実行し、Solidity コードをデバッグする方法が必要になります。

また、Solidity コードをクライアント アプリケーション (この場合は React アプリケーション) で実行できるコードにコンパイルする方法も必要です。これがどのように機能するかについては、後で詳しく説明します。

Hardhat は、フルスタック開発用に設計された Ethereum 開発環境およびフレームワークであり、このチュートリアルで使用するフレームワークです。

エコシステム内の他の同様のツールとしては、Ganache、Truffle、Foundry などがあります。

2. Ethereum ネットワーク クライアント ライブラリ

React アプリケーションでは、デプロイされたスマート コントラクトと対話する方法が必要です。新しいトランザクションを送信するだけでなく、データを読み取る方法も必要になります。

ethers.js は、React、Vue、Angular、Svelte などのクライアント側 JavaScript アプリケーションから Ethereum ブロックチェーンとそのエコシステムと対話するための完全かつコンパクトなライブラリを目指しています。これが私たちが使用するライブラリです。

エコシステムにおけるもう一つの人気のある選択肢はweb3.jsです

3. メタマスク

Metamask はアカウント管理の処理を支援し、現在のユーザーをブロックチェーンに接続します。 MetaMask を使用すると、ユーザーはサイトのコンテキストからアカウントとキーを分離しながら、さまざまな方法で管理できます。

ユーザーが MetaMask ウォレットを接続すると、開発者は、Web3 互換ブラウザのユーザーを MetaMask ユーザーとして認識する、グローバルに利用可能な Ethereum API (window.ethereum) と対話できるようになります。また、トランザクションの署名を要求するたびに、MetaMask はユーザーに可能な限りわかりやすい方法でプロンプトを表示します。

4. 反応する

React は、Web アプリケーション、ユーザー インターフェイス、UI コンポーネントを構築するためのフロントエンド JavaScript ライブラリです。これは Facebook と多くの個人開発者および企業によって管理されています。

React とそのメタフレームワークの広大なエコシステム (Next.js、Gatsby、Redwood、Blitz.js など) は、従来の SPA、静的サイト ジェネレーター、サーバー側レンダリング、およびこれら 3 つを組み合わせたものなど、あらゆるタイプのデプロイメント ターゲットをサポートしています。 React はフロントエンドの分野で引き続き優位に立っているようで、少なくとも近い将来はそうあり続けると思います。

5. グラフ

Ethereum のようなブロックチェーン上に構築されたほとんどのアプリケーションでは、チェーンから直接データを読み取るのは困難で時間がかかるため、以前は個人や企業が独自の集中型インデックス サーバーを構築し、それらのサーバーから API リクエストを処理していました。これには多大なエンジニアリングおよびハードウェア リソースが必要となり、分散化に必要なセキュリティ プロパティが損なわれます。

Graph は、ブロックチェーン データをクエリするためのインデックス プロトコルであり、完全に分散化されたアプリケーションの作成を可能にし、この問題を解決して、アプリケーションが使用できる豊富な GraphQL クエリ レイヤーを提供します。このガイドでは、アプリケーションのサブグラフは構築しませんが、後のチュートリアルで構築します。

The Graph を使用してブロックチェーン API を構築する方法については、「Ethereum での GraphQL API の構築」をご覧ください。


私たちが構築するもの


このチュートリアルでは、いくつかの基本的なスマート コントラクトを構築、デプロイ、接続します。

  1. イーサリアムブロックチェーン上でメッセージを作成および更新する契約

  2. トークンを発行するための契約。これにより、契約の所有者はトークンを他の人に送信したり、トークンの残高を読んだりすることができ、新しいトークンの所有者はトークンを他の人に送信することもできます。

また、ユーザーが次のことができる React フロントエンドも構築します。

  1. ブロックチェーンにデプロイされたコントラクトからの挨拶を読む

  2. 更新のご挨拶

  3. 新しく発行されたトークンを自分のアドレスから別のアドレスに送信する

  4. トークンを受け取ったら、そのトークンを他の人に送信できるようにします

  5. ブロックチェーンにデプロイされた契約からトークン残高を読み取る

前提条件

  • ローカルマシンにNode.jsがインストールされている

  • ブラウザにインストールされたChrome拡張機能MetaMask

このガイドでは、チュートリアル全体を通してテスト ネットワーク上で偽の/テストの Ether を使用するため、Ethereum を所有する必要はありません。


始める


まず、新しい React アプリケーションを作成します。

npx create-react-app react-dapp

次に、新しいディレクトリに移動し、NPM または Yarn を使用して ethers.js と hardhat をインストールします。

npm install ethers hardhat @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers

Ethereum開発環境をインストールして設定する

次に、Hardhat を使用して新しい Ethereum 開発環境を初期化します。

npx hardhat

? What do you want to do? Create a sample project
? Hardhat project root:

ルート ディレクトリに次のセクションが作成されているはずです。

  • hardhat.config.js - Hardhat のセットアップ全体 (つまり、構成、プラグイン、カスタム タスク) がこのファイルに含まれています。

  • scrips - 実行時にスマートコントラクトをデプロイする sample-script.js というスクリプトを含むフォルダー

  • test - サンプルのテスト スクリプトを含むフォルダー contracts - サンプルの Solidity スマート コントラクトを含むフォルダー

MetaMask 構成の問題により、HardHat 構成のチェーン ID を 1337 に更新する必要があります。また、コンパイルされたコントラクト成果物の場所を React アプリケーションの src ディレクトリに更新する必要があります。

これらの更新を行うには、hardhat.config.js を開き、module.exports を次のように更新します。

module.exports = {
solidity: "0.8.4",
paths: {
artifacts: './src/artifacts',
},
networks: {
hardhat: {
chainId: 1337
}
}
};


当社のスマートコントラクト


次に、contracts/Greeter.sol で提供されているサンプル契約を見てみましょう。

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "hardhat/console.sol";


contract Greeter {
string greeting;

constructor(string memory _greeting) {
console.log("Deploying a Greeter with greeting:", _greeting);
greeting = _greeting;
}

function greet() public view returns (string memory) {
return greeting;
}

function setGreeting(string memory _greeting) public {
console.log("Changing greeting from '%s' to '%s'", greeting, _greeting);
greeting = _greeting;
}
}

これは非常に基本的なスマート コントラクトです。デプロイされると、Greeting 変数が設定され、挨拶を返すために呼び出すことができる関数 (greet) が公開されます。

また、ユーザーが挨拶を更新できるようにする関数 (setGreeting) も公開します。これらのメソッドは、Ethereum ブロックチェーンにデプロイされると、ユーザーが操作できるようになります。


Ethereumブロックチェーンの読み取りと書き込み


スマート コントラクトと対話する方法には、読み取りと書き込み/トランザクションの 2 つがあります。私たちのコントラクトでは、greet は読み取りと見なすことができ、setGreeting は書き込み/トランザクションと見なすことができます。

トランザクションを書き込むとき、または初期化するときには、トランザクションをブロックチェーンに書き込むために料金を支払う必要があります。これを行うには、ガスを支払う必要があります。ガスは、Ethereum ブロックチェーン上でトランザクションを正常に実行し、契約を実行するために必要な料金または価格です。

ブロックチェーンからデータを読み取るだけで、何も変更または更新しない限り、トランザクションを実行する必要はなく、そのためのガスやコストも発生しません。呼び出した関数は接続しているノードによってのみ実行されるため、料金は発生せず、読み取りは無料です。

React アプリケーションでは、ethers.js ライブラリ、コントラクト アドレス、および hardhat によってコントラクトから作成される ABI の組み合わせを使用して、スマート コントラクトと対話します。

ABI とは何ですか? ABI は、Application Binary Interface の略です。これは、クライアント アプリケーションと、対話するスマート コントラクトがデプロイされる Ethereum ブロックチェーン間のインターフェイスと考えることができます。

ABI は通常、HardHat などの開発フレームワークによって Solidity スマート コントラクトからコンパイルされます。スマート コントラクトの ABI は、Etherscan でもよく見つかります。


ABI のコンパイル


スマート コントラクトの基礎を理解し、ABI が何であるかがわかったので、プロジェクト用の ABI をコンパイルしてみましょう。

これを行うには、コマンド ラインに移動して次のコマンドを実行します。

npx hardhat compile

これで、src ディレクトリに「artifacts」という新しいフォルダーが表示されるはずです。

arthits/contracts/Greeter.json ファイルには、プロパティの 1 つとして ABI が含まれています。 ABI を使用する必要がある場合は、JavaScript ファイルからインポートできます。

import Greeter from './artifacts/contracts/Greeter.sol/Greeter.json'

次のようにして ABI を参照できます。

console.log("Greeter ABI: ", Greeter.abi)

Ethers.js では人間が読める ABI も有効になりますが、このチュートリアルではそれについては説明しません。


ローカルネットワーク/ブロックチェーンを展開して使用する


次に、スマート コントラクトをローカル ブロックチェーンにデプロイしてテストしてみましょう。

ローカル ネットワークにデプロイするには、まずローカル テスト ノードを起動する必要があります。これを行うには、CLI を開いて次のコマンドを実行します。

npx hardhat node

このコマンドを実行すると、アドレスと秘密鍵のリストが表示されます。

これらは、スマート コントラクトをデプロイしてテストするために使用できる、作成された 20 個のテスト アカウントとアドレスです。各アカウントには 10,000 テスト イーサもロードされました。後ほど、テスト アカウントを MetaMask にインポートして使用できるようにする方法を学習します。

次に、契約をテスト ネットワークにデプロイする必要があります。まず、scripts/sample-script.js の名前を scripts/deploy.js に更新します。

これで、デプロイメント スクリプトを実行し、ローカル ネットワークにデプロイするフラグを CLI に提供できます。

npx hardhat run scripts/deploy.js --network localhost

このスクリプトを実行すると、スマート コントラクトがローカル テスト ネットワークにデプロイされ、対話を開始できるようになります。

契約が展開されると、ローカル ネットワークを開始したときに作成した最初のアカウントが使用されました。

CLI の出力を見ると、次のようなものが表示されるはずです。

Greeter deployed to: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0

このアドレスは、クライアント アプリケーションでスマート コントラクトと通信するために使用します。このアドレスはクライアント アプリケーションから接続するときに必要となるため、使用可能な状態にしておいてください。

スマート コントラクトにトランザクションを送信するには、npx ハードハット ノードの実行時に作成したアカウントの 1 つを使用して MetaMask ウォレットに接続する必要があります。 CLI でログアウトした契約のリストに、アカウント番号秘密鍵が表示されます。

➜ react-dapp git:(main) npx hardhat node
Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/

Accounts
========
Account #0: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 (10000 ETH)
Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

...

このアカウントを MetaMask にインポートして、そこで利用可能な Eth テスト コインの一部を使い始めることができます。

これを行うには、まずMetaMaskを開いてテストネットワークを有効にします。

次に、ネットワークを Localhost 8545 に更新します。

次に、MetaMask で、アカウント メニューから [アカウントのインポート] をクリックします。

CLI 経由でログアウトした秘密キーの 1 つをコピーして貼り付け、[インポート] をクリックします。アカウントがインポートされると、アカウントに Eth が表示されます。

スマート コントラクトがデプロイされ、使用するアカウントができたので、React アプリケーションからスマート コントラクトとのやり取りを開始できます。


Reactクライアントの接続


このチュートリアルでは、CSS などを使用して優れた UI を構築することについては気にせず、コア機能に 100% 焦点を当てて、すぐに使い始めることができるようにします。そこから、必要に応じて見栄えを良くすることができます。

それでは、React アプリケーションで達成したい 2 つの目標を確認してみましょう。

  1. スマートコントラクトから現在の挨拶の値を取得する

  2. ユーザーが挨拶の値を更新できるようにします

これを知った上で、どうすればいいのでしょうか?これを実現するには、次のことを行う必要があります。

  1. 入力フィールドと入力値を管理するためのローカル状態を作成する(挨拶の更新)

  2. アプリケーションがユーザーのMetaMaskアカウントに接続してトランザクションに署名できるようにします

  3. スマートコントラクトの読み取りと書き込みのための関数を作成する

これを行うには、src/App.js を開き、次のコードで更新して、greeterAddress の値をスマート コントラクトのアドレスに設定します。

import './App.css';
import { useState } from 'react';
import { ethers } from 'ethers'
import Greeter from './artifacts/contracts/Greeter.sol/Greeter.json'

// Update with the contract address logged out to the CLI when it was deployed
const greeterAddress = "your-contract-address"

function App() {
// store greeting in local state
const [greeting, setGreetingValue] = useState()

// request access to the user's MetaMask account
async function requestAccount() {
await window.ethereum.request({ method: 'eth_requestAccounts' });
}

// call the smart contract, read the current greeting value
async function fetchGreeting() {
if (typeof window.ethereum !== 'undefined') {
const provider = new ethers.providers.Web3Provider(window.ethereum)
const contract = new ethers.Contract(greeterAddress, Greeter.abi, provider)
try {
const data = await contract.greet()
console.log('data: ', data)
} catch (err) {
console.log("Error: ", err)
}
}
}

// call the smart contract, send an update
async function setGreeting() {
if (!greeting) return
if (typeof window.ethereum !== 'undefined') {
await requestAccount()
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner()
const contract = new ethers.Contract(greeterAddress, Greeter.abi, signer)
const transaction = await contract.setGreeting(greeting)
await transaction.wait()
fetchGreeting()
}
}

return (
<div className="App">
<header className="App-header">
<button onClick={fetchGreeting}>Fetch Greeting</button>
<button onClick={setGreeting}>Set Greeting</button>
<input onChange={e => setGreetingValue(e.target.value)} placeholder="Set greeting" />
</header>
</div>
);
}

export default App;

テストするには、React サーバーを起動します。

npm start

アプリケーションが読み込まれると、現在の挨拶を取得し、コンソールにログアウトできるようになります。 MetaMask ウォレットで契約に署名し、Ether テスト コインを使用することで、挨拶を更新することもできます。


ライブテストネットワークを展開して使用する


Ropsten、Rinkeby、Kovan などの Ethereum テスト ネットワークがいくつかあり、メインネットにデプロイしなくても、パブリックにアクセス可能なバージョンの契約を取得するためにデプロイすることもできます。このチュートリアルでは、Ropsten テスト ネットワークにデプロイします。

まず、MetaMask ウォレットを更新して、Ropsten ネットワークに接続します。

次に、このテスト ファウセットにアクセスして、このチュートリアルの残りの部分で使用するテスト Ether を自分に送信します。

Infura や Alchemy などのサービスにサインアップすることで、Ropsten (またはその他のテスト ネットワーク) にアクセスできます (このチュートリアルでは Infura を使用します)。

Infura または Alchemy でアプリケーションを作成すると、次のようなエンドポイントが作成されます。

https://ropsten.infura.io/v3/your-project-id

デプロイメントに使用するアカウントのウォレット アドレスを含めるには、Infura または Alchemy アプリケーション構成で ALLOWLIST ETHEREUM ADDRESSES を必ず設定してください。

テスト ネットワークに展開するには、追加のネットワーク情報を使用してハードハット構成を更新する必要があります。設定する必要があるものの一つは、展開元のウォレットの秘密鍵です。

秘密鍵を取得するには、MetaMask からエクスポートします。

この値をアプリケーション内でハードコーディングするのではなく、環境変数のようなものとして設定することをお勧めします。

次に、次の構成でネットワーク プロパティを追加します。

module.exports = {
defaultNetwork: "hardhat",
paths: {
artifacts: './src/artifacts',
},
networks: {
hardhat: {},
ropsten: {
url: "https://ropsten.infura.io/v3/your-project-id",
accounts: [`0x${your-private-key}`]
}
},
solidity: "0.8.4",
};

デプロイするには、次のスクリプトを実行します。

npx hardhat run scripts/deploy.js --network ropsten

契約がデプロイされると、契約とのやり取りを開始できるようになります。これで、Etherscan Ropstenテストネットエクスプローラーでライブ契約を表示できるようになります。


トークンの発行


スマート コントラクトの最も一般的な使用例の 1 つはトークンの作成です。その方法を見てみましょう。これらすべてがどのように機能するかをより深く理解したら、もう少し速く進むことができます。

メインのコントラクト ディレクトリに Token.sol という新しいファイルを作成します。

次に、次のスマート コントラクトで Token.sol を更新します。

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "hardhat/console.sol";

contract Token {
string public name = "Nader Dabit Token";
string public symbol = "NDT";
uint public totalSupply = 1000000;
mapping(address => uint) balances;

constructor() {
balances[msg.sender] = totalSupply;
}

function transfer(address to, uint amount) external {
require(balances[msg.sender] >= amount, "Not enough tokens");
balances[msg.sender] -= amount;
balances[to] += amount;
}

function balanceOf(address account) external view returns (uint) {
return balances[account];
}
}

このトークン契約はデモンストレーション目的のみであり、ERC20 に準拠していないことに注意してください。ここではERC20トークンを紹介します

この契約により、「Nader Dabit Token」と呼ばれる新しいトークンが作成され、供給量が 1,000,000 に設定されます。

次に、契約書をコンパイルします。

npx hardhat compile

次に、scripts/deploy.js のデプロイ スクリプトを更新して、この新しいトークン コントラクトを含めます。

const hre = require("hardhat");

async function main() {
const [deployer] = await hre.ethers.getSigners();

console.log(
"Deploying contracts with the account:",
deployer.address
);

const Greeter = await hre.ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello, World!");

const Token = await hre.ethers.getContractFactory("Token");
const token = await Token.deploy();

await greeter.deployed();
await token.deployed();

console.log("Greeter deployed to:", greeter.address);
console.log("Token deployed to:", token.address);
}

main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});

これで、この新しいコントラクトをローカルまたは Ropsten ネットワークにデプロイできるようになりました。

npx hardhat run scripts/deploy.js --network localhost

契約がデプロイされると、これらのトークンを他のアドレスに送信できるようになります。

これを実行するには、動作させるために必要なクライアント コードを更新します。

import './App.css';
import { useState } from 'react';
import { ethers } from 'ethers'
import Greeter from './artifacts/contracts/Greeter.sol/Greeter.json'
import Token from './artifacts/contracts/Token.sol/Token.json'

const greeterAddress = "your-contract-address"
const tokenAddress = "your-contract-address"

function App() {
const [greeting, setGreetingValue] = useState()
const [userAccount, setUserAccount] = useState()
const [amount, setAmount] = useState()

async function requestAccount() {
await window.ethereum.request({ method: 'eth_requestAccounts' });
}

async function fetchGreeting() {
if (typeof window.ethereum !== 'undefined') {
const provider = new ethers.providers.Web3Provider(window.ethereum)
console.log({ provider })
const contract = new ethers.Contract(greeterAddress, Greeter.abi, provider)
try {
const data = await contract.greet()
console.log('data: ', data)
} catch (err) {
console.log("Error: ", err)
}
}
}

async function getBalance() {
if (typeof window.ethereum !== 'undefined') {
const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' })
const provider = new ethers.providers.Web3Provider(window.ethereum);
const contract = new ethers.Contract(tokenAddress, Token.abi, provider)
const balance = await contract.balanceOf(account);
console.log("Balance: ", balance.toString());
}
}

async function setGreeting() {
if (!greeting) return
if (typeof window.ethereum !== 'undefined') {
await requestAccount()
const provider = new ethers.providers.Web3Provider(window.ethereum);
console.log({ provider })
const signer = provider.getSigner()
const contract = new ethers.Contract(greeterAddress, Greeter.abi, signer)
const transaction = await contract.setGreeting(greeting)
await transaction.wait()
fetchGreeting()
}
}

async function sendCoins() {
if (typeof window.ethereum !== 'undefined') {
await requestAccount()
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const contract = new ethers.Contract(tokenAddress, Token.abi, signer);
const transation = await contract.transfer(userAccount, amount);
await transation.wait();
console.log(`${amount} Coins successfully sent to ${userAccount}`);
}
}

return (
<div className="App">
<header className="App-header">
<button onClick={fetchGreeting}>Fetch Greeting</button>
<button onClick={setGreeting}>Set Greeting</button>
<input onChange={e => setGreetingValue(e.target.value)} placeholder="Set greeting" />

<br />
<button onClick={getBalance}>Get Balance</button>
<button onClick={sendCoins}>Send Coins</button>
<input onChange={e => setUserAccount(e.target.value)} placeholder="Account ID" />
<input onChange={e => setAmount(e.target.value)} placeholder="Amount" />
</header>
</div>
);
}

export default App;

次に、アプリケーションを実行します。

npm start

「残高を取得」をクリックすると、コンソールにログアウトしたアカウントに 1,000,000 コインがあることが確認できるはずです。

「トークンのインポート」をクリックすると、MetaMask でそれらを表示することもできます。

次に、「カスタム トークン」をクリックしてトークン コントラクト アドレスを入力し、カスタム トークンを追加します。 (トークンの小数点以下の桁数を尋ねられた場合は、0 を選択してください) これで、トークンがウォレットで利用できるようになります。

次に、これらのコインを別のアドレスに送信してみます。

これを行うには、別のアカウントのアドレスをコピーし、更新された React UI を使用してそのアドレスに送信します。トークンの金額を確認すると、元の金額からアドレスに送信した金額を差し引いた金額と等しくなります。


ERC20トークン


ERC20 トークン標準は、すべての ERC20 トークンに適用される一連のルールを定義し、トークン同士が簡単にやり取りできるようにします。 ERC20 を使用すると、Ethereum ブロックチェーン上の他のトークンと相互運用可能な独自のトークンを簡単に作成できます。

ERC20 標準を使用して独自のトークンを構築する方法を見てみましょう。

まず、OpenZepplin スマート コントラクト ライブラリをインストールし、そこに基本 ERC20 トークンをインポートします。

npm install @openzeppelin/contracts

次に、ERC20 コントラクトを拡張(または継承)してトークンを作成します。

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract NDToken is ERC20 {
constructor(string memory name, string memory symbol) ERC20(name, symbol) {
_mint(msg.sender, 100000 * (10 ** 18));
}
}

コンストラクターを使用するとトークンの名前とシンボルを設定でき、_mint 関数を使用するとトークンを作成し、その量を設定できます。

デフォルトでは、ERC20 は小数点以下の桁数を 18 に設定しているため、_mint 関数では 100,000 に 10 の 18 乗を掛けて、小数点以下の桁数がそれぞれ 18 のトークンを合計 100,000 個発行します (1 Eth が 10 から 18 の wei で構成されるのと同様)。

デプロイするには、コンストラクター値 (名前とシンボル) を渡す必要があるため、デプロイ スクリプトで次の操作を実行できます。

const NDToken = await hre.ethers.getContractFactory("NDToken");
const ndToken = await NDToken.deploy("Nader Dabit Token", "NDT");

元の ERC20 トークンを拡張すると、トークンは次の機能をすべて継承します。

function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)

デプロイされると、これらの関数のいずれかを使用して新しいスマート コントラクトと対話できるようになります。 ERC20トークンの別の例については、[Solidity by example)( https://solidity-by-example.org/app/erc20/)をご覧ください。


結論は


さて、ここでは多くのことを説明しましたが、私にとってこれはこのスタックを使い始めるための基本/中核であり、これらすべてを学習している人としてだけでなく、将来必要になるかもしれない何かを参照する必要がある場合にも、私が持っていたいものです。たくさんのことを学べたことを願っています。

MetaMask に加えて複数のウォレットをサポートしたい場合は、Web3Modal をチェックしてください。Web3Modal を使用すると、非常にシンプルでカスタマイズ可能な構成で、アプリに複数のプロバイダーのサポートを簡単に実装できます。

今後のチュートリアルとガイドでは、より複雑なスマート コントラクトの開発と、それらをサブグラフとしてデプロイしてその上に GraphQL API を公開し、ページネーションや全文検索などの機能を実装する方法について詳しく説明します。

また、IPFS や Web3 データベースなどのテクノロジーを使用して、分散型でデータを保存する方法についても説明します。


<<:  中国初のデジタル人民元路上駐車スペースが深センで開設

>>:  グレイスケール・ビットコイン・トラストのマイナスプレミアムは26.5%となり、過去最低を記録した。ビットコインETFは新たな戦場となるか?

推薦する

古いバージョンのEthereumクライアントにはバグがありますが、フォークは発生しません。

著者 |秦暁峰制作 |オデイリープラネットデイリーThe Block によると、Ethereum ク...

分散型台帳技術は、国境を越えた決済システムとデジタル法定通貨ネットワークという2つの改革の原動力を銀行にもたらす。

現在、私たちが送金に使用しているシステムは、規模が大きく、複雑で、費用がかかり、ルールもありません。...

ビットコイン会社BTCSは2015年に1000万ドルの純損失を被った

BTCS Ltd.(旧称Bitcoin Shop Ltd.)は2015年度の財務報告書を発表し、同社...

マイニングマシン、取引所、オラクル、ブロックチェーン業界では「水を売る」ことの方が「金の採掘」よりも利益が大きいのでしょうか?

投資の世界では、ほとんどの人が知っている「水売り理論」という理論があります。物語はこうです。「19世...

神徒青春:ブロックチェーンの応用シナリオを見つけるのは簡単ではない

先日、グローバル・シェアード・ファイナンス100フォーラムの深セン春季サミットが成功裏に開催されまし...

ポルカドットエコシステム POW コイン Kulupu (KLP) マイニングチュートリアル

プロジェクト紹介: Kulupu は、Proof-of-Work (POW) コンセンサス メカニズ...

ビットコインのマイニングには自己破壊メカニズムがある

これはビットコイン鉱山です。電気料金と収入の矛盾、そして地方分権の理念からの逸脱から、長期的な解決策...

ビットコインの価格は再び暴落するでしょうか?投資リスクとリターンを比較検討する

ビットコインの価格は、マウントゴックスに関する懸念を相殺する好ましいマクロ経済的要因によって上昇して...

デジタル通貨取引所のOKexは、複数の秘密鍵保有者との連絡が取れなくなったため出金を停止した。

10月16日、大手デジタル通貨取引所OKexは通貨引き出しの停止を発表する発表を行った。発表による...

ビットコイン技術の将来は深刻な危機に陥る可能性がある

ユニオン・パシフィック・インベストメンツのパートナーであるフレッド・ウィルソン氏は最近、自身の個人ブ...

AusecureがUpholdと統合、Upholdメンバーはゴールドを購入できるようになりました

Uphold は最近、Ausecure との提携を発表しており、今後 Uphold のメンバーは実際...