伊藤  直子

伊藤 直子

1648110000

TruffleSuiteを使用してEthereumスマートコントラクトを開発する

独自のブロックチェーンアプリケーションを作成する方法を考えたことはありますか?イーサリアムに関して言えば、それはスマートコントラクトから始まります。

このチュートリアルでは、Solidity言語で記述されたスマートコントラクトに焦点を当てます。Truffle Suiteを使用して、ローカルバージョンのEthereumブロックチェーンをデプロイし、Ethereum仮想マシン(EVM)を使用してスマートコントラクトをコンパイルします。

上記のテクノロジーに精通していない場合は、最初にWeb3.jsを使用したイーサリアムブロックチェーン開発のガイドを読むことをお勧めします。

トリュフスイートとは何ですか?

イーサリアムは、アプリケーションを実行できるようにするブロックチェーンです。コードは、スマートコントラクトの形式でSolidity言語で記述されています。これらのコントラクトをコンパイルするには、スマートコントラクトを機械可読コードに変換するEthereumコンパイラが必要です。

Truffle Suiteは、イーサリアムでのブロックチェーン開発用に特別に作成されたツールのコレクションです。スイートには、次の3つのソフトウェアが含まれています。

  1. トリュフ、スマートコントラクト開発のフレームワーク
  2. Ganacheは、テストと開発のためにローカルネットワーク上に個人のEthereumブロックチェーンを設定できるようにします
  3. Drizzleは、DAppユーザーインターフェイスの作成に使用され、すぐに使用できるコンポーネントのコレクションが含まれています

ライブラリとソフトウェアのセットアップ

このチュートリアルでは、Ethereumブロックチェーン、スマートコントラクトコンパイラ、通信用のJavaScriptライブラリなど、いくつかのノードパッケージとソフトウェアが必要です。

ガナッシュのインストール

スマートコントラクトはイーサリアムブロックチェーンで実行されるため、展開とテストにスマートコントラクトが必要です。ライブチェーンにデプロイすることもできますが、ガス料金としてEtherが必要になります。それでは、ローカルチェーンを設定して、そこでテストを行いましょう。コードについて確信があり、アプリケーションを配布する準備ができたら、ライブチェーンにデプロイできます。

Ganacheは、コンピューターにインストールされ、ローカルホストで実行されるローカルチェーンです。TruffleSuiteのWebサイトからGanacheをダウンロードしてインストールします。

Ganacheがそれぞれ100ETHで10個のアカウントを提供したことがわかります。これらは偽のエーテルなので、興奮しないでください。また、チェーンは7545ポートの127.0.0.1で実行されています。これらのアカウントを使用して、このチェーンにスマートコントラクトを展開します。エーテルは私たちがガス料金を支払うのを助けます。

Node.jsのインストール

このプロジェクトにはNode.jsが必要なので、システムにインストールされていることを確認してください。Node.jsの公式ウェブサイトからダウンロードできます。

Web3.jsのインストール

Web3.jsは、JavaScriptを介したイーサリアムブロックチェーンとの通信を可能にするJavaScriptライブラリです。開発に役立つ機能がたくさん組み込まれています。

npmまたはを使用してWeb3.jsをインストールできますyarn

npm install web3 -g

Truffleのインストール

Truffleは、スマートコントラクト用のコンパイラを提供します。SolidityコードをGanacheブロックチェーンにデプロイできる機械可読コードに変換するために必要です。

次のコマンドを使用してTruffleをインストールします。

npm install truffle -g

スマートコントラクトの作成

スマートコントラクトを作成するには、最初に、すべてのSolidityファイルを保持するプロジェクトディレクトリを作成する必要があります。solidity名前を付けて作成し、を使用してターミナルのディレクトリに移動しましょうcd solidity

現在、私たちのプロジェクトは空です。それを操作するには、ボイラープレートコードが必要です。たとえば、ReactでUIを作成する場合は、Reactをインストールする必要があります。

Truffleは、ボックスと呼ばれるいくつかのパッケージをすでに提供しています。これらのパッケージは、Truffle、Ganache、React、Web3、Reduxなどのさまざまなフレームワークのバンドルであり、Vue.js開発者向けのパッケージがあります。これらは一緒になって、クライアントUIからブロックチェーンスマートコントラクトまで、エンドツーエンドのアプリケーション開発を完了します。

この記事では、Truffleが提供するReactボックスを使用します。

Reactボックスのインストール

Reactボックスをインストールするには、次のコマンドを実行します。

truffle unbox react

これにより、Web3.js、React、Ganache CLI、Truffle、およびEthereumがインストールされます。ある意味では、最初のステップでこれらすべてのユーティリティをインストールする必要はありませんでした。

このチュートリアルでは、ReactやブラウザーベースのUIには焦点を当てません。代わりに、スマートコントラクトを作成し、ターミナルのみで処理します。

プロジェクトのディレクトリ構造は次のようになります。

clientこれは、アプリケーションのUIを作成できるReactプロジェクトフォルダーです。その中には、コンパイルされたスマートコントラクトをJSON形式で保持するフォルダー(client/ src/ )があります。contractsこれらのファイルは、スマートコントラクトをコンパイルするときに生成されます。これらには、ABI、バイトコード、およびその他の情報が含まれています。

上の画像から、2つのJSONファイルがあることがわかります。これは、Reactバンドルを箱から出したときに、Truffleがすでに2つのスマートコントラクトを提供していたためです。それらのいずれかを開くと、次のようなコードが見つかります。

{
  "contractName": "SimpleStorage",
  "abi": [
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "x",
          "type": "uint256"
        }
      ],
      "name": "set",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "get",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    }
  ],
  "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"project:/contracts/SimpleStorage.sol\":\"SimpleStorage\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"project:/contracts/SimpleStorage.sol\":{\"keccak256\":\"0x512df1603c5f878921707d236bc53d974afe05b4d9de4b6094249bac5ab60efe\",\"urls\":[\"bzz-raw://0d6de97971b1c387f984fa7ea1d9ec10f8a63d68cc63bf8bd00d8c3a7c9e3ee1\",\"dweb:/ipfs/Qmbt92T34sHzedfJjDsvbisvLhRtghNwS6VW8tqrGkrqTD\"]}},\"version\":1}",
  "bytecode": "0x608060405234801561001057600080fd5b5060c68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806360fe47b11460375780636d4ce63c146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050607e565b005b60686088565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea265627a7a7231582044ccb2c2d46346d523107088f3e26a4c8a2ec3ec8b2e3a6edb1bc8574d5c5f5264736f6c63430005100032",
  "deployedBytecode": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c806360fe47b11460375780636d4ce63c146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050607e565b005b60686088565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea265627a7a7231582044ccb2c2d46346d523107088f3e26a4c8a2ec3ec8b2e3a6edb1bc8574d5c5f5264736f6c63430005100032",
  "sourceMap": "66:176:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66:176:1;;;;;;;",
  "deployedSourceMap": "66:176:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66:176:1;;;;;;;;;;;;;;;;;;;;;;;;113:53;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;113:53:1;;;;;;;;;;;;;;;;;:::i;:::-;;170:70;;;:::i;:::-;;;;;;;;;;;;;;;;;;;113:53;160:1;147:10;:14;;;;113:53;:::o;170:70::-;206:4;225:10;;218:17;;170:70;:::o",
  "source": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.21 <0.7.0;\n\ncontract SimpleStorage {\n  uint storedData;\n\n  function set(uint x) public {\n    storedData = x;\n  }\n\n  function get() public view returns (uint) {\n    return storedData;\n  }\n}\n",
  "sourcePath": "C:\\Users\\akash\\Desktop\\solidity\\contracts\\SimpleStorage.sol",
  "ast": {
    "absolutePath": "project:/contracts/SimpleStorage.sol",
    "exportedSymbols": {
      "SimpleStorage": [
        59
      ]
    },
    "id": 60,
    "nodeType": "SourceUnit",
    "nodes": [
      {
        "id": 38,
        "literals": [
          "solidity",
          ">=",
          "0.4",
          ".21",
          "<",
          "0.7",
          ".0"
        ],
        "nodeType": "PragmaDirective",
        "src": "32:32:1"
      },
      {
        "baseContracts": [],
        "contractDependencies": [],
        "contractKind": "contract",
        "documentation": null,
        "fullyImplemented": true,
        "id": 59,
        "linearizedBaseContracts": [
          59
        ],
        "name": "SimpleStorage",
        "nodeType": "ContractDefinition",
        "nodes": [
          {
            "constant": false,
            "id": 40,
            "name": "storedData",
            "nodeType": "VariableDeclaration",
            "scope": 59,
            "src": "93:15:1",
            "stateVariable": true,
            "storageLocation": "default",
            "typeDescriptions": {
              "typeIdentifier": "t_uint256",
              "typeString": "uint256"
            },
            "typeName": {
              "id": 39,
              "name": "uint",
              "nodeType": "ElementaryTypeName",
              "src": "93:4:1",
              "typeDescriptions": {
                "typeIdentifier": "t_uint256",
                "typeString": "uint256"
              }
            },
            "value": null,
            "visibility": "internal"
          },
          {
            "body": {
              "id": 49,
              "nodeType": "Block",
              "src": "141:25:1",
              "statements": [
                {
                  "expression": {
                    "argumentTypes": null,
                    "id": 47,
                    "isConstant": false,
                    "isLValue": false,
                    "isPure": false,
                    "lValueRequested": false,
                    "leftHandSide": {
                      "argumentTypes": null,
                      "id": 45,
                      "name": "storedData",
                      "nodeType": "Identifier",
                      "overloadedDeclarations": [],
                      "referencedDeclaration": 40,
                      "src": "147:10:1",
                      "typeDescriptions": {
                        "typeIdentifier": "t_uint256",
                        "typeString": "uint256"
                      }
                    },
                    "nodeType": "Assignment",
                    "operator": "=",
                    "rightHandSide": {
                      "argumentTypes": null,
                      "id": 46,
                      "name": "x",
                      "nodeType": "Identifier",
                      "overloadedDeclarations": [],
                      "referencedDeclaration": 42,
                      "src": "160:1:1",
                      "typeDescriptions": {
                        "typeIdentifier": "t_uint256",
                        "typeString": "uint256"
                      }
                    },
                    "src": "147:14:1",
                    "typeDescriptions": {
                      "typeIdentifier": "t_uint256",
                      "typeString": "uint256"
                    }
                  },
                  "id": 48,
                  "nodeType": "ExpressionStatement",
                  "src": "147:14:1"
                }
              ]
            },
            "documentation": null,
            "id": 50,
            "implemented": true,
            "kind": "function",
            "modifiers": [],
            "name": "set",
            "nodeType": "FunctionDefinition",
            "parameters": {
              "id": 43,
              "nodeType": "ParameterList",
              "parameters": [
                {
                  "constant": false,
                  "id": 42,
                  "name": "x",
                  "nodeType": "VariableDeclaration",
                  "scope": 50,
                  "src": "126:6:1",
                  "stateVariable": false,
                  "storageLocation": "default",
                  "typeDescriptions": {
                    "typeIdentifier": "t_uint256",
                    "typeString": "uint256"
                  },
                  "typeName": {
                    "id": 41,
                    "name": "uint",
                    "nodeType": "ElementaryTypeName",
                    "src": "126:4:1",
                    "typeDescriptions": {
                      "typeIdentifier": "t_uint256",
                      "typeString": "uint256"
                    }
                  },
                  "value": null,
                  "visibility": "internal"
                }
              ],
              "src": "125:8:1"
            },
            "returnParameters": {
              "id": 44,
              "nodeType": "ParameterList",
              "parameters": [],
              "src": "141:0:1"
            },
            "scope": 59,
            "src": "113:53:1",
            "stateMutability": "nonpayable",
            "superFunction": null,
            "visibility": "public"
          },
          {
            "body": {
              "id": 57,
              "nodeType": "Block",
              "src": "212:28:1",
              "statements": [
                {
                  "expression": {
                    "argumentTypes": null,
                    "id": 55,
                    "name": "storedData",
                    "nodeType": "Identifier",
                    "overloadedDeclarations": [],
                    "referencedDeclaration": 40,
                    "src": "225:10:1",
                    "typeDescriptions": {
                      "typeIdentifier": "t_uint256",
                      "typeString": "uint256"
                    }
                  },
                  "functionReturnParameters": 54,
                  "id": 56,
                  "nodeType": "Return",
                  "src": "218:17:1"
                }
              ]
            },
            "documentation": null,
            "id": 58,
            "implemented": true,
            "kind": "function",
            "modifiers": [],
            "name": "get",
            "nodeType": "FunctionDefinition",
            "parameters": {
              "id": 51,
              "nodeType": "ParameterList",
              "parameters": [],
              "src": "182:2:1"
            },
            "returnParameters": {
              "id": 54,
              "nodeType": "ParameterList",
              "parameters": [
                {
                  "constant": false,
                  "id": 53,
                  "name": "",
                  "nodeType": "VariableDeclaration",
                  "scope": 58,
                  "src": "206:4:1",
                  "stateVariable": false,
                  "storageLocation": "default",
                  "typeDescriptions": {
                    "typeIdentifier": "t_uint256",
                    "typeString": "uint256"
                  },
                  "typeName": {
                    "id": 52,
                    "name": "uint",
                    "nodeType": "ElementaryTypeName",
                    "src": "206:4:1",
                    "typeDescriptions": {
                      "typeIdentifier": "t_uint256",
                      "typeString": "uint256"
                    }
                  },
                  "value": null,
                  "visibility": "internal"
                }
              ],
              "src": "205:6:1"
            },
            "scope": 59,
            "src": "170:70:1",
            "stateMutability": "view",
            "superFunction": null,
            "visibility": "public"
          }
        ],
        "scope": 60,
        "src": "66:176:1"
      }
    ],
    "src": "32:211:1"
  },
  "legacyAST": {
    "attributes": {
      "absolutePath": "project:/contracts/SimpleStorage.sol",
      "exportedSymbols": {
        "SimpleStorage": [
          59
        ]
      }
    },
    "children": [
      {
        "attributes": {
          "literals": [
            "solidity",
            ">=",
            "0.4",
            ".21",
            "<",
            "0.7",
            ".0"
          ]
        },
        "id": 38,
        "name": "PragmaDirective",
        "src": "32:32:1"
      },
      {
        "attributes": {
          "baseContracts": [
            null
          ],
          "contractDependencies": [
            null
          ],
          "contractKind": "contract",
          "documentation": null,
          "fullyImplemented": true,
          "linearizedBaseContracts": [
            59
          ],
          "name": "SimpleStorage",
          "scope": 60
        },
        "children": [
          {
            "attributes": {
              "constant": false,
              "name": "storedData",
              "scope": 59,
              "stateVariable": true,
              "storageLocation": "default",
              "type": "uint256",
              "value": null,
              "visibility": "internal"
            },
            "children": [
              {
                "attributes": {
                  "name": "uint",
                  "type": "uint256"
                },
                "id": 39,
                "name": "ElementaryTypeName",
                "src": "93:4:1"
              }
            ],
            "id": 40,
            "name": "VariableDeclaration",
            "src": "93:15:1"
          },
          {
            "attributes": {
              "documentation": null,
              "implemented": true,
              "isConstructor": false,
              "kind": "function",
              "modifiers": [
                null
              ],
              "name": "set",
              "scope": 59,
              "stateMutability": "nonpayable",
              "superFunction": null,
              "visibility": "public"
            },
            "children": [
              {
                "children": [
                  {
                    "attributes": {
                      "constant": false,
                      "name": "x",
                      "scope": 50,
                      "stateVariable": false,
                      "storageLocation": "default",
                      "type": "uint256",
                      "value": null,
                      "visibility": "internal"
                    },
                    "children": [
                      {
                        "attributes": {
                          "name": "uint",
                          "type": "uint256"
                        },
                        "id": 41,
                        "name": "ElementaryTypeName",
                        "src": "126:4:1"
                      }
                    ],
                    "id": 42,
                    "name": "VariableDeclaration",
                    "src": "126:6:1"
                  }
                ],
                "id": 43,
                "name": "ParameterList",
                "src": "125:8:1"
              },
              {
                "attributes": {
                  "parameters": [
                    null
                  ]
                },
                "children": [],
                "id": 44,
                "name": "ParameterList",
                "src": "141:0:1"
              },
              {
                "children": [
                  {
                    "children": [
                      {
                        "attributes": {
                          "argumentTypes": null,
                          "isConstant": false,
                          "isLValue": false,
                          "isPure": false,
                          "lValueRequested": false,
                          "operator": "=",
                          "type": "uint256"
                        },
                        "children": [
                          {
                            "attributes": {
                              "argumentTypes": null,
                              "overloadedDeclarations": [
                                null
                              ],
                              "referencedDeclaration": 40,
                              "type": "uint256",
                              "value": "storedData"
                            },
                            "id": 45,
                            "name": "Identifier",
                            "src": "147:10:1"
                          },
                          {
                            "attributes": {
                              "argumentTypes": null,
                              "overloadedDeclarations": [
                                null
                              ],
                              "referencedDeclaration": 42,
                              "type": "uint256",
                              "value": "x"
                            },
                            "id": 46,
                            "name": "Identifier",
                            "src": "160:1:1"
                          }
                        ],
                        "id": 47,
                        "name": "Assignment",
                        "src": "147:14:1"
                      }
                    ],
                    "id": 48,
                    "name": "ExpressionStatement",
                    "src": "147:14:1"
                  }
                ],
                "id": 49,
                "name": "Block",
                "src": "141:25:1"
              }
            ],
            "id": 50,
            "name": "FunctionDefinition",
            "src": "113:53:1"
          },
          {
            "attributes": {
              "documentation": null,
              "implemented": true,
              "isConstructor": false,
              "kind": "function",
              "modifiers": [
                null
              ],
              "name": "get",
              "scope": 59,
              "stateMutability": "view",
              "superFunction": null,
              "visibility": "public"
            },
            "children": [
              {
                "attributes": {
                  "parameters": [
                    null
                  ]
                },
                "children": [],
                "id": 51,
                "name": "ParameterList",
                "src": "182:2:1"
              },
              {
                "children": [
                  {
                    "attributes": {
                      "constant": false,
                      "name": "",
                      "scope": 58,
                      "stateVariable": false,
                      "storageLocation": "default",
                      "type": "uint256",
                      "value": null,
                      "visibility": "internal"
                    },
                    "children": [
                      {
                        "attributes": {
                          "name": "uint",
                          "type": "uint256"
                        },
                        "id": 52,
                        "name": "ElementaryTypeName",
                        "src": "206:4:1"
                      }
                    ],
                    "id": 53,
                    "name": "VariableDeclaration",
                    "src": "206:4:1"
                  }
                ],
                "id": 54,
                "name": "ParameterList",
                "src": "205:6:1"
              },
              {
                "children": [
                  {
                    "attributes": {
                      "functionReturnParameters": 54
                    },
                    "children": [
                      {
                        "attributes": {
                          "argumentTypes": null,
                          "overloadedDeclarations": [
                            null
                          ],
                          "referencedDeclaration": 40,
                          "type": "uint256",
                          "value": "storedData"
                        },
                        "id": 55,
                        "name": "Identifier",
                        "src": "225:10:1"
                      }
                    ],
                    "id": 56,
                    "name": "Return",
                    "src": "218:17:1"
                  }
                ],
                "id": 57,
                "name": "Block",
                "src": "212:28:1"
              }
            ],
            "id": 58,
            "name": "FunctionDefinition",
            "src": "170:70:1"
          }
        ],
        "id": 59,
        "name": "ContractDefinition",
        "src": "66:176:1"
      }
    ],
    "id": 60,
    "name": "SourceUnit",
    "src": "32:211:1"
  },
  "compiler": {
    "name": "solc",
    "version": "0.5.16+commit.9c3226ce.Emscripten.clang"
  },
  "networks": {
    "5777": {
      "events": {},
      "links": {},
      "address": "0xc21DB75B9B17Cb43Cd983A16BaA6c73b314B1E8f",
      "transactionHash": "0xada7b561df968c3d23485d25cbd22a66d1d4b76a86137dbf1bef858e816ff0c2"
    }
  },
  "schemaVersion": "3.4.3",
  "updatedAt": "2021-10-29T10:14:41.665Z",
  "networkType": "ethereum",
  "devdoc": {
    "methods": {}
  },
  "userdoc": {
    "methods": {}
  }
}

上記の大規模なコードブロックには、ABI、バイトコード、ソースコード、およびその他の大量の情報が含まれています。ABIから、呼び出し可能な関数のリストを取得できます。このファイルには、ネットワークID、契約アドレス、トランザクションハッシュ、コンパイラの詳細、チェーンの詳細などのすべての情報が含まれています。

なぜこのファイルがUIディレクトリにあるのか疑問に思われるかもしれません。これは、Web3.jsが操作に使用するためです。このファイルにより、Web3.jsはチェーン上のスマートコントラクトを認識できます。また、ABIは関数のリストを取得するのに役立ちます。

  • contractsSolidityファイルを保持するディレクトリです。ここにすべてのソースコードを配置します
  • migrationsどのSolidityファイルをチェーンに移行する必要があるかをTruffleに通知するファイルです
  • testテストファイルを作成するためのものです
  • truffle-config.jsTruffleのいくつかの構成設定が含まれています。

内容は次のtruffle-config.jsとおりです。

const path = require("path");

module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // to customize your Truffle configuration!
  contracts_build_directory: path.join(__dirname, "client/src/contracts"),
  networks: {
    develop: {
      port: 8545
    }
  }
};

ご覧のとおり、client/src/contractsコンパイルされたコードを保持するように設定されています。開発ネットワークはポート8545に設定されています。これは、このボックスがGanacheを実行しているポートです。

Ganacheをインストールした上部を見ると、7545ポートで実行されていたことがわかりますが、インストールされたGanacheで7545がすでに使用されているため、これは8545で実行されています。必要に応じて、このポートを7545に変更できます。トリュフは、ボックスで提供されるアカウントの代わりに、ガナッシュとインストールしたアカウントを使用します。私はそれを8545に保っています。

Solidityでスマートコントラクトを書く

次に、コードを記述します。CRUD操作を行い、果物のリストを管理します。

基本的に、私たちのアプリケーションはさまざまな果物のリストを表示します。フルーツを追加、更新、削除できます。

以前にアプリを開発したことがある場合は、必ずおなじみの手順に従います。

  1. 果物の名前を保持する配列を作成します
  2. 新しい値を配列にプッシュする関数を作成します
  3. 指定されたインデックスの値を変更する関数を作成します
  4. 値を削除する関数を作成する
  5. 配列を返す関数を作成します

それでは、Solidityでコードを書いてみましょう。

ディレクトリに新しいファイルを作成し、contractsそれを呼び出しますFruits.sol。サポートしているライセンスとSolidityバージョンを示すことからファイルを開始します。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

次に、すべてのコードを記述するスコープを宣言しcontractます。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {

}

果物を保持する配列を作成します。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {
  string[] myFruits;
}

これはプライベート修飾子を持つ文字列配列です。つまり、コントラクトの外部からアクセスできないため、値を直接変更することはできません。

次に、新しい値を追加する関数を作成します。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {
  string[] myFruits;

  function addFruit(string memory fruitName) public {
      myFruits.push(fruitName);
  }
}

addFruit文字列をパラメータとして受け入れる、という関数を作成しましたfruitName。これはパブリックとして宣言されているため、UIまたはターミナルから呼び出すことができます。関数本体では、値を配列にプッシュするだけです。

値を更新します。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {
  string[] myFruits;

  function addFruit(string memory fruitName) public {
      myFruits.push(fruitName);
  }

  function updateFruit(uint fruitIndex, string memory newFruitName) public returns (bool) {
      if(myFruits.length > fruitIndex){
          myFruits[fruitIndex] = newFruitName;
          return true;
      }
      return false;
  }
}

updateFruitfruitIndex2つの引数とを受け入れnewFruitName、ブール値を返します。これは次のように機能します。インデックスが配列の範囲外の場合は、を返しますfalse。それ以外の場合は、指定されたインデックスで新しく提供されたフルーツ名で配列の値を変更し、を返しtrueます。

次の手順は、削除機能を作成することです。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {
  string[] myFruits;

  function addFruit(string memory fruitName) public {
      myFruits.push(fruitName);
  }

  function updateFruit(uint fruitIndex, string memory newFruitName) public returns (bool) {
      if(myFruits.length > fruitIndex){
          myFruits[fruitIndex] = newFruitName;
          return true;
      }
      return false;
  }

  function deleteFruit(uint fruitIndex) public returns (bool) {
      if(myFruits.length > fruitIndex){
          for(uint i=fruitIndex; i < myFruits.length-1; i++){
              myFruits[i] = myFruits[i+1];
          }

          myFruits.pop();

          return true;
      }
      return false;
  }
}

ここでは、インデックスの範囲外条件をチェックしてから、値を指定されたインデックスの次の値に置き換えることで配列を更新しています。このように、提供されたインデックスの値は失われます。最後に、最後の値を取り出して返しtrueます。

最後のステップは、配列を返すことです。配列のすべての値を読み取るには:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {
  string[] myFruits;

  function addFruit(string memory fruitName) public {
      myFruits.push(fruitName);
  }

  function updateFruit(uint fruitIndex, string memory newFruitName) public returns (bool) {
      if(myFruits.length > fruitIndex){
          myFruits[fruitIndex] = newFruitName;
          return true;
      }
      return false;
  }

  function deleteFruit(uint fruitIndex) public returns (bool) {
      if(myFruits.length > fruitIndex){
          for(uint i=fruitIndex; i < myFruits.length-1; i++){
              myFruits[i] = myFruits[i+1];
          }

          myFruits.pop();

          return true;
      }
      return false;
  }

  function getFruits() public view returns (string[] memory) {
      return myFruits;
  }
}

Truffleを使用したスマートコントラクトのコンパイル

スマートコントラクトのコーディングが完了したので、Truffleを使用してコンパイルします。ただし、最初に移行ファイルを作成して、これをチェーンに移行することをTruffleに示す必要があります。

フォルダをチェックインすると、migration2つのJavaScriptファイルが見つかります。

それぞれ番号で始まるので、3番目のファイルは3で始まります。コードはほぼ標準です。それ2_deploy_contractsは:

var SimpleStorage = artifacts.require("./SimpleStorage.sol");

module.exports = function(deployer) {
  deployer.deploy(SimpleStorage);
};

移行ファイルを追加しましょう3_fruits_contracts

var FruitsList = artifacts.require("./Fruits.sol");

module.exports = function(deployer) {
  deployer.deploy(FruitsList);
};

フルーツコントラクトをコンパイルして移行する準備が整いました。ターミナルに移動し、以下を実行します。

> truffle develop

このコマンドは、トリュフコンソールを起動します。また、チェーンネットワーク、アカウント、ニーモニックなどの情報も表示されます。

Ganacheはデフォルトで10個のアカウントを提供します。彼らはあなたのために異なります。これらの秘密鍵は、この記事のすべての訪問者に表示されるため、ライブチェーンでは使用しないでください。つまり、誰でもこれらのアカウントにアクセスできます。

次に、次のコマンドを使用してコントラクトをコンパイルします。

> compile

ファイルが作成されてclient/src/contractsいるかどうかを確認できます。Fruits.json

次のコマンドを使用して、コンパイルされたファイルをチェーンに移行できます。

> migrate

これにより、3つのスマートコントラクトすべてがチェーンに移行されます。



最後に、私たちのアプリケーションはイーサリアムチェーン上にあります。ガス料金に0.00153イーサを費やし、トランザクションが最初のアカウントから発生したことがわかります。デフォルトでは、常に最初のアカウントが使用されます。さまざまな操作ができるようになりました。

果物のリストを取得する

Web3.jsを使用して、さまざまな値に反応して書き込むことができます。まず、コントラクトのインスタンスを変数に格納しましょう。

let instance = await Fruits.deployed()

awaitブロックチェーン内のすべてが非同期であり、promiseを返すため、使用しています。

次に、このインスタンスを使用して配列を取得します。

> let fruits = instance.getFruits()
undefined
> fruits
[]

現在、fruits配列には値がないため、空の配列が返されます。

リストに果物を追加する

いくつかの果物を追加しましょう:

> let result = await instance.addFruit("Apple")
undefined

resultトランザクションを保持します。すべての読み取り操作は無料ですが、ブロックチェーンの変更につながる操作にはガス料金がかかることを忘れないでください。この操作は、配列に値を追加し、データを変更します。したがって、トランザクションとして記録されます。

これで、配列を再度読み取って内容を確認できます。

リストにさらにいくつかの果物を追加しましょう。

> await instance.addFruit("Mango")
> await instance.addFruit("Banana")
> await instance.addFruit("Orange")
> await instance.addFruit("Guava")
> await instance.addFruit("Pineapple")
> await instance.addFruit("Water Melon")
> await instance.addFruit("Papaya")
> await instance.addFruit("Strawberry")

これらすべての操作にはEtherのコストがかかることを忘れないでください。一度に複数の果物の値を受け入れるための関数をコントラクトに作成することで、手数料を節約できます。

今すぐ配列を読んでください:

果物の名前を更新する

上の画像で、「Guava」のつづりを「Guavva」と間違えたことがわかります。updateFruit関数を使って修正しましょう。インデックスと新しい値を受け入れます。インデックスは4です。

> await instance.updateFruit(4, "Guava")

今すぐ配列を読んでみましょう:

スペルは正常に修正されました。

果物の名前を削除する

最後の操作は、値を削除することです。

> await instance.deleteFruit(4)

値を読み取ります。

ご覧のとおり、「Guava」アイテムはリストから削除されています。

結論

スマートコントラクトを作成してブロックチェーンにデプロイするのは楽しくて強力です。これは、従来のプログラミングからの新しい視点を提供します。これらの手法を使用して、オンライン投票、デジタルバンク、ウォレット、オークションなど、あらゆる種類のアプリケーションを作成できます。

このチュートリアルでは、スマートコントラクトを作成してローカルチェーンにデプロイする方法を示しました。これで、イーサリアムのテストネットワークにデプロイしてみることができます。

一度に複数のフルーツを追加してトランザクションコストを節約するなど、より多くの機能を導入することで、現在のアプリを改善できます。また、ユニークな果物のみを許可するようにチェックを入れることもできます。配列の代わりに、マッピングを使用してみてください。

ハッピーコーディング! 

出典:https ://blog.logrocket.com/truffle-suite  

#truffle #ethereum #web3 

What is GEEK

Buddha Community

TruffleSuiteを使用してEthereumスマートコントラクトを開発する
伊藤  直子

伊藤 直子

1648110000

TruffleSuiteを使用してEthereumスマートコントラクトを開発する

独自のブロックチェーンアプリケーションを作成する方法を考えたことはありますか?イーサリアムに関して言えば、それはスマートコントラクトから始まります。

このチュートリアルでは、Solidity言語で記述されたスマートコントラクトに焦点を当てます。Truffle Suiteを使用して、ローカルバージョンのEthereumブロックチェーンをデプロイし、Ethereum仮想マシン(EVM)を使用してスマートコントラクトをコンパイルします。

上記のテクノロジーに精通していない場合は、最初にWeb3.jsを使用したイーサリアムブロックチェーン開発のガイドを読むことをお勧めします。

トリュフスイートとは何ですか?

イーサリアムは、アプリケーションを実行できるようにするブロックチェーンです。コードは、スマートコントラクトの形式でSolidity言語で記述されています。これらのコントラクトをコンパイルするには、スマートコントラクトを機械可読コードに変換するEthereumコンパイラが必要です。

Truffle Suiteは、イーサリアムでのブロックチェーン開発用に特別に作成されたツールのコレクションです。スイートには、次の3つのソフトウェアが含まれています。

  1. トリュフ、スマートコントラクト開発のフレームワーク
  2. Ganacheは、テストと開発のためにローカルネットワーク上に個人のEthereumブロックチェーンを設定できるようにします
  3. Drizzleは、DAppユーザーインターフェイスの作成に使用され、すぐに使用できるコンポーネントのコレクションが含まれています

ライブラリとソフトウェアのセットアップ

このチュートリアルでは、Ethereumブロックチェーン、スマートコントラクトコンパイラ、通信用のJavaScriptライブラリなど、いくつかのノードパッケージとソフトウェアが必要です。

ガナッシュのインストール

スマートコントラクトはイーサリアムブロックチェーンで実行されるため、展開とテストにスマートコントラクトが必要です。ライブチェーンにデプロイすることもできますが、ガス料金としてEtherが必要になります。それでは、ローカルチェーンを設定して、そこでテストを行いましょう。コードについて確信があり、アプリケーションを配布する準備ができたら、ライブチェーンにデプロイできます。

Ganacheは、コンピューターにインストールされ、ローカルホストで実行されるローカルチェーンです。TruffleSuiteのWebサイトからGanacheをダウンロードしてインストールします。

Ganacheがそれぞれ100ETHで10個のアカウントを提供したことがわかります。これらは偽のエーテルなので、興奮しないでください。また、チェーンは7545ポートの127.0.0.1で実行されています。これらのアカウントを使用して、このチェーンにスマートコントラクトを展開します。エーテルは私たちがガス料金を支払うのを助けます。

Node.jsのインストール

このプロジェクトにはNode.jsが必要なので、システムにインストールされていることを確認してください。Node.jsの公式ウェブサイトからダウンロードできます。

Web3.jsのインストール

Web3.jsは、JavaScriptを介したイーサリアムブロックチェーンとの通信を可能にするJavaScriptライブラリです。開発に役立つ機能がたくさん組み込まれています。

npmまたはを使用してWeb3.jsをインストールできますyarn

npm install web3 -g

Truffleのインストール

Truffleは、スマートコントラクト用のコンパイラを提供します。SolidityコードをGanacheブロックチェーンにデプロイできる機械可読コードに変換するために必要です。

次のコマンドを使用してTruffleをインストールします。

npm install truffle -g

スマートコントラクトの作成

スマートコントラクトを作成するには、最初に、すべてのSolidityファイルを保持するプロジェクトディレクトリを作成する必要があります。solidity名前を付けて作成し、を使用してターミナルのディレクトリに移動しましょうcd solidity

現在、私たちのプロジェクトは空です。それを操作するには、ボイラープレートコードが必要です。たとえば、ReactでUIを作成する場合は、Reactをインストールする必要があります。

Truffleは、ボックスと呼ばれるいくつかのパッケージをすでに提供しています。これらのパッケージは、Truffle、Ganache、React、Web3、Reduxなどのさまざまなフレームワークのバンドルであり、Vue.js開発者向けのパッケージがあります。これらは一緒になって、クライアントUIからブロックチェーンスマートコントラクトまで、エンドツーエンドのアプリケーション開発を完了します。

この記事では、Truffleが提供するReactボックスを使用します。

Reactボックスのインストール

Reactボックスをインストールするには、次のコマンドを実行します。

truffle unbox react

これにより、Web3.js、React、Ganache CLI、Truffle、およびEthereumがインストールされます。ある意味では、最初のステップでこれらすべてのユーティリティをインストールする必要はありませんでした。

このチュートリアルでは、ReactやブラウザーベースのUIには焦点を当てません。代わりに、スマートコントラクトを作成し、ターミナルのみで処理します。

プロジェクトのディレクトリ構造は次のようになります。

clientこれは、アプリケーションのUIを作成できるReactプロジェクトフォルダーです。その中には、コンパイルされたスマートコントラクトをJSON形式で保持するフォルダー(client/ src/ )があります。contractsこれらのファイルは、スマートコントラクトをコンパイルするときに生成されます。これらには、ABI、バイトコード、およびその他の情報が含まれています。

上の画像から、2つのJSONファイルがあることがわかります。これは、Reactバンドルを箱から出したときに、Truffleがすでに2つのスマートコントラクトを提供していたためです。それらのいずれかを開くと、次のようなコードが見つかります。

{
  "contractName": "SimpleStorage",
  "abi": [
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "x",
          "type": "uint256"
        }
      ],
      "name": "set",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "get",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    }
  ],
  "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"project:/contracts/SimpleStorage.sol\":\"SimpleStorage\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"project:/contracts/SimpleStorage.sol\":{\"keccak256\":\"0x512df1603c5f878921707d236bc53d974afe05b4d9de4b6094249bac5ab60efe\",\"urls\":[\"bzz-raw://0d6de97971b1c387f984fa7ea1d9ec10f8a63d68cc63bf8bd00d8c3a7c9e3ee1\",\"dweb:/ipfs/Qmbt92T34sHzedfJjDsvbisvLhRtghNwS6VW8tqrGkrqTD\"]}},\"version\":1}",
  "bytecode": "0x608060405234801561001057600080fd5b5060c68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806360fe47b11460375780636d4ce63c146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050607e565b005b60686088565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea265627a7a7231582044ccb2c2d46346d523107088f3e26a4c8a2ec3ec8b2e3a6edb1bc8574d5c5f5264736f6c63430005100032",
  "deployedBytecode": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c806360fe47b11460375780636d4ce63c146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050607e565b005b60686088565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea265627a7a7231582044ccb2c2d46346d523107088f3e26a4c8a2ec3ec8b2e3a6edb1bc8574d5c5f5264736f6c63430005100032",
  "sourceMap": "66:176:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66:176:1;;;;;;;",
  "deployedSourceMap": "66:176:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66:176:1;;;;;;;;;;;;;;;;;;;;;;;;113:53;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;113:53:1;;;;;;;;;;;;;;;;;:::i;:::-;;170:70;;;:::i;:::-;;;;;;;;;;;;;;;;;;;113:53;160:1;147:10;:14;;;;113:53;:::o;170:70::-;206:4;225:10;;218:17;;170:70;:::o",
  "source": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.21 <0.7.0;\n\ncontract SimpleStorage {\n  uint storedData;\n\n  function set(uint x) public {\n    storedData = x;\n  }\n\n  function get() public view returns (uint) {\n    return storedData;\n  }\n}\n",
  "sourcePath": "C:\\Users\\akash\\Desktop\\solidity\\contracts\\SimpleStorage.sol",
  "ast": {
    "absolutePath": "project:/contracts/SimpleStorage.sol",
    "exportedSymbols": {
      "SimpleStorage": [
        59
      ]
    },
    "id": 60,
    "nodeType": "SourceUnit",
    "nodes": [
      {
        "id": 38,
        "literals": [
          "solidity",
          ">=",
          "0.4",
          ".21",
          "<",
          "0.7",
          ".0"
        ],
        "nodeType": "PragmaDirective",
        "src": "32:32:1"
      },
      {
        "baseContracts": [],
        "contractDependencies": [],
        "contractKind": "contract",
        "documentation": null,
        "fullyImplemented": true,
        "id": 59,
        "linearizedBaseContracts": [
          59
        ],
        "name": "SimpleStorage",
        "nodeType": "ContractDefinition",
        "nodes": [
          {
            "constant": false,
            "id": 40,
            "name": "storedData",
            "nodeType": "VariableDeclaration",
            "scope": 59,
            "src": "93:15:1",
            "stateVariable": true,
            "storageLocation": "default",
            "typeDescriptions": {
              "typeIdentifier": "t_uint256",
              "typeString": "uint256"
            },
            "typeName": {
              "id": 39,
              "name": "uint",
              "nodeType": "ElementaryTypeName",
              "src": "93:4:1",
              "typeDescriptions": {
                "typeIdentifier": "t_uint256",
                "typeString": "uint256"
              }
            },
            "value": null,
            "visibility": "internal"
          },
          {
            "body": {
              "id": 49,
              "nodeType": "Block",
              "src": "141:25:1",
              "statements": [
                {
                  "expression": {
                    "argumentTypes": null,
                    "id": 47,
                    "isConstant": false,
                    "isLValue": false,
                    "isPure": false,
                    "lValueRequested": false,
                    "leftHandSide": {
                      "argumentTypes": null,
                      "id": 45,
                      "name": "storedData",
                      "nodeType": "Identifier",
                      "overloadedDeclarations": [],
                      "referencedDeclaration": 40,
                      "src": "147:10:1",
                      "typeDescriptions": {
                        "typeIdentifier": "t_uint256",
                        "typeString": "uint256"
                      }
                    },
                    "nodeType": "Assignment",
                    "operator": "=",
                    "rightHandSide": {
                      "argumentTypes": null,
                      "id": 46,
                      "name": "x",
                      "nodeType": "Identifier",
                      "overloadedDeclarations": [],
                      "referencedDeclaration": 42,
                      "src": "160:1:1",
                      "typeDescriptions": {
                        "typeIdentifier": "t_uint256",
                        "typeString": "uint256"
                      }
                    },
                    "src": "147:14:1",
                    "typeDescriptions": {
                      "typeIdentifier": "t_uint256",
                      "typeString": "uint256"
                    }
                  },
                  "id": 48,
                  "nodeType": "ExpressionStatement",
                  "src": "147:14:1"
                }
              ]
            },
            "documentation": null,
            "id": 50,
            "implemented": true,
            "kind": "function",
            "modifiers": [],
            "name": "set",
            "nodeType": "FunctionDefinition",
            "parameters": {
              "id": 43,
              "nodeType": "ParameterList",
              "parameters": [
                {
                  "constant": false,
                  "id": 42,
                  "name": "x",
                  "nodeType": "VariableDeclaration",
                  "scope": 50,
                  "src": "126:6:1",
                  "stateVariable": false,
                  "storageLocation": "default",
                  "typeDescriptions": {
                    "typeIdentifier": "t_uint256",
                    "typeString": "uint256"
                  },
                  "typeName": {
                    "id": 41,
                    "name": "uint",
                    "nodeType": "ElementaryTypeName",
                    "src": "126:4:1",
                    "typeDescriptions": {
                      "typeIdentifier": "t_uint256",
                      "typeString": "uint256"
                    }
                  },
                  "value": null,
                  "visibility": "internal"
                }
              ],
              "src": "125:8:1"
            },
            "returnParameters": {
              "id": 44,
              "nodeType": "ParameterList",
              "parameters": [],
              "src": "141:0:1"
            },
            "scope": 59,
            "src": "113:53:1",
            "stateMutability": "nonpayable",
            "superFunction": null,
            "visibility": "public"
          },
          {
            "body": {
              "id": 57,
              "nodeType": "Block",
              "src": "212:28:1",
              "statements": [
                {
                  "expression": {
                    "argumentTypes": null,
                    "id": 55,
                    "name": "storedData",
                    "nodeType": "Identifier",
                    "overloadedDeclarations": [],
                    "referencedDeclaration": 40,
                    "src": "225:10:1",
                    "typeDescriptions": {
                      "typeIdentifier": "t_uint256",
                      "typeString": "uint256"
                    }
                  },
                  "functionReturnParameters": 54,
                  "id": 56,
                  "nodeType": "Return",
                  "src": "218:17:1"
                }
              ]
            },
            "documentation": null,
            "id": 58,
            "implemented": true,
            "kind": "function",
            "modifiers": [],
            "name": "get",
            "nodeType": "FunctionDefinition",
            "parameters": {
              "id": 51,
              "nodeType": "ParameterList",
              "parameters": [],
              "src": "182:2:1"
            },
            "returnParameters": {
              "id": 54,
              "nodeType": "ParameterList",
              "parameters": [
                {
                  "constant": false,
                  "id": 53,
                  "name": "",
                  "nodeType": "VariableDeclaration",
                  "scope": 58,
                  "src": "206:4:1",
                  "stateVariable": false,
                  "storageLocation": "default",
                  "typeDescriptions": {
                    "typeIdentifier": "t_uint256",
                    "typeString": "uint256"
                  },
                  "typeName": {
                    "id": 52,
                    "name": "uint",
                    "nodeType": "ElementaryTypeName",
                    "src": "206:4:1",
                    "typeDescriptions": {
                      "typeIdentifier": "t_uint256",
                      "typeString": "uint256"
                    }
                  },
                  "value": null,
                  "visibility": "internal"
                }
              ],
              "src": "205:6:1"
            },
            "scope": 59,
            "src": "170:70:1",
            "stateMutability": "view",
            "superFunction": null,
            "visibility": "public"
          }
        ],
        "scope": 60,
        "src": "66:176:1"
      }
    ],
    "src": "32:211:1"
  },
  "legacyAST": {
    "attributes": {
      "absolutePath": "project:/contracts/SimpleStorage.sol",
      "exportedSymbols": {
        "SimpleStorage": [
          59
        ]
      }
    },
    "children": [
      {
        "attributes": {
          "literals": [
            "solidity",
            ">=",
            "0.4",
            ".21",
            "<",
            "0.7",
            ".0"
          ]
        },
        "id": 38,
        "name": "PragmaDirective",
        "src": "32:32:1"
      },
      {
        "attributes": {
          "baseContracts": [
            null
          ],
          "contractDependencies": [
            null
          ],
          "contractKind": "contract",
          "documentation": null,
          "fullyImplemented": true,
          "linearizedBaseContracts": [
            59
          ],
          "name": "SimpleStorage",
          "scope": 60
        },
        "children": [
          {
            "attributes": {
              "constant": false,
              "name": "storedData",
              "scope": 59,
              "stateVariable": true,
              "storageLocation": "default",
              "type": "uint256",
              "value": null,
              "visibility": "internal"
            },
            "children": [
              {
                "attributes": {
                  "name": "uint",
                  "type": "uint256"
                },
                "id": 39,
                "name": "ElementaryTypeName",
                "src": "93:4:1"
              }
            ],
            "id": 40,
            "name": "VariableDeclaration",
            "src": "93:15:1"
          },
          {
            "attributes": {
              "documentation": null,
              "implemented": true,
              "isConstructor": false,
              "kind": "function",
              "modifiers": [
                null
              ],
              "name": "set",
              "scope": 59,
              "stateMutability": "nonpayable",
              "superFunction": null,
              "visibility": "public"
            },
            "children": [
              {
                "children": [
                  {
                    "attributes": {
                      "constant": false,
                      "name": "x",
                      "scope": 50,
                      "stateVariable": false,
                      "storageLocation": "default",
                      "type": "uint256",
                      "value": null,
                      "visibility": "internal"
                    },
                    "children": [
                      {
                        "attributes": {
                          "name": "uint",
                          "type": "uint256"
                        },
                        "id": 41,
                        "name": "ElementaryTypeName",
                        "src": "126:4:1"
                      }
                    ],
                    "id": 42,
                    "name": "VariableDeclaration",
                    "src": "126:6:1"
                  }
                ],
                "id": 43,
                "name": "ParameterList",
                "src": "125:8:1"
              },
              {
                "attributes": {
                  "parameters": [
                    null
                  ]
                },
                "children": [],
                "id": 44,
                "name": "ParameterList",
                "src": "141:0:1"
              },
              {
                "children": [
                  {
                    "children": [
                      {
                        "attributes": {
                          "argumentTypes": null,
                          "isConstant": false,
                          "isLValue": false,
                          "isPure": false,
                          "lValueRequested": false,
                          "operator": "=",
                          "type": "uint256"
                        },
                        "children": [
                          {
                            "attributes": {
                              "argumentTypes": null,
                              "overloadedDeclarations": [
                                null
                              ],
                              "referencedDeclaration": 40,
                              "type": "uint256",
                              "value": "storedData"
                            },
                            "id": 45,
                            "name": "Identifier",
                            "src": "147:10:1"
                          },
                          {
                            "attributes": {
                              "argumentTypes": null,
                              "overloadedDeclarations": [
                                null
                              ],
                              "referencedDeclaration": 42,
                              "type": "uint256",
                              "value": "x"
                            },
                            "id": 46,
                            "name": "Identifier",
                            "src": "160:1:1"
                          }
                        ],
                        "id": 47,
                        "name": "Assignment",
                        "src": "147:14:1"
                      }
                    ],
                    "id": 48,
                    "name": "ExpressionStatement",
                    "src": "147:14:1"
                  }
                ],
                "id": 49,
                "name": "Block",
                "src": "141:25:1"
              }
            ],
            "id": 50,
            "name": "FunctionDefinition",
            "src": "113:53:1"
          },
          {
            "attributes": {
              "documentation": null,
              "implemented": true,
              "isConstructor": false,
              "kind": "function",
              "modifiers": [
                null
              ],
              "name": "get",
              "scope": 59,
              "stateMutability": "view",
              "superFunction": null,
              "visibility": "public"
            },
            "children": [
              {
                "attributes": {
                  "parameters": [
                    null
                  ]
                },
                "children": [],
                "id": 51,
                "name": "ParameterList",
                "src": "182:2:1"
              },
              {
                "children": [
                  {
                    "attributes": {
                      "constant": false,
                      "name": "",
                      "scope": 58,
                      "stateVariable": false,
                      "storageLocation": "default",
                      "type": "uint256",
                      "value": null,
                      "visibility": "internal"
                    },
                    "children": [
                      {
                        "attributes": {
                          "name": "uint",
                          "type": "uint256"
                        },
                        "id": 52,
                        "name": "ElementaryTypeName",
                        "src": "206:4:1"
                      }
                    ],
                    "id": 53,
                    "name": "VariableDeclaration",
                    "src": "206:4:1"
                  }
                ],
                "id": 54,
                "name": "ParameterList",
                "src": "205:6:1"
              },
              {
                "children": [
                  {
                    "attributes": {
                      "functionReturnParameters": 54
                    },
                    "children": [
                      {
                        "attributes": {
                          "argumentTypes": null,
                          "overloadedDeclarations": [
                            null
                          ],
                          "referencedDeclaration": 40,
                          "type": "uint256",
                          "value": "storedData"
                        },
                        "id": 55,
                        "name": "Identifier",
                        "src": "225:10:1"
                      }
                    ],
                    "id": 56,
                    "name": "Return",
                    "src": "218:17:1"
                  }
                ],
                "id": 57,
                "name": "Block",
                "src": "212:28:1"
              }
            ],
            "id": 58,
            "name": "FunctionDefinition",
            "src": "170:70:1"
          }
        ],
        "id": 59,
        "name": "ContractDefinition",
        "src": "66:176:1"
      }
    ],
    "id": 60,
    "name": "SourceUnit",
    "src": "32:211:1"
  },
  "compiler": {
    "name": "solc",
    "version": "0.5.16+commit.9c3226ce.Emscripten.clang"
  },
  "networks": {
    "5777": {
      "events": {},
      "links": {},
      "address": "0xc21DB75B9B17Cb43Cd983A16BaA6c73b314B1E8f",
      "transactionHash": "0xada7b561df968c3d23485d25cbd22a66d1d4b76a86137dbf1bef858e816ff0c2"
    }
  },
  "schemaVersion": "3.4.3",
  "updatedAt": "2021-10-29T10:14:41.665Z",
  "networkType": "ethereum",
  "devdoc": {
    "methods": {}
  },
  "userdoc": {
    "methods": {}
  }
}

上記の大規模なコードブロックには、ABI、バイトコード、ソースコード、およびその他の大量の情報が含まれています。ABIから、呼び出し可能な関数のリストを取得できます。このファイルには、ネットワークID、契約アドレス、トランザクションハッシュ、コンパイラの詳細、チェーンの詳細などのすべての情報が含まれています。

なぜこのファイルがUIディレクトリにあるのか疑問に思われるかもしれません。これは、Web3.jsが操作に使用するためです。このファイルにより、Web3.jsはチェーン上のスマートコントラクトを認識できます。また、ABIは関数のリストを取得するのに役立ちます。

  • contractsSolidityファイルを保持するディレクトリです。ここにすべてのソースコードを配置します
  • migrationsどのSolidityファイルをチェーンに移行する必要があるかをTruffleに通知するファイルです
  • testテストファイルを作成するためのものです
  • truffle-config.jsTruffleのいくつかの構成設定が含まれています。

内容は次のtruffle-config.jsとおりです。

const path = require("path");

module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // to customize your Truffle configuration!
  contracts_build_directory: path.join(__dirname, "client/src/contracts"),
  networks: {
    develop: {
      port: 8545
    }
  }
};

ご覧のとおり、client/src/contractsコンパイルされたコードを保持するように設定されています。開発ネットワークはポート8545に設定されています。これは、このボックスがGanacheを実行しているポートです。

Ganacheをインストールした上部を見ると、7545ポートで実行されていたことがわかりますが、インストールされたGanacheで7545がすでに使用されているため、これは8545で実行されています。必要に応じて、このポートを7545に変更できます。トリュフは、ボックスで提供されるアカウントの代わりに、ガナッシュとインストールしたアカウントを使用します。私はそれを8545に保っています。

Solidityでスマートコントラクトを書く

次に、コードを記述します。CRUD操作を行い、果物のリストを管理します。

基本的に、私たちのアプリケーションはさまざまな果物のリストを表示します。フルーツを追加、更新、削除できます。

以前にアプリを開発したことがある場合は、必ずおなじみの手順に従います。

  1. 果物の名前を保持する配列を作成します
  2. 新しい値を配列にプッシュする関数を作成します
  3. 指定されたインデックスの値を変更する関数を作成します
  4. 値を削除する関数を作成する
  5. 配列を返す関数を作成します

それでは、Solidityでコードを書いてみましょう。

ディレクトリに新しいファイルを作成し、contractsそれを呼び出しますFruits.sol。サポートしているライセンスとSolidityバージョンを示すことからファイルを開始します。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

次に、すべてのコードを記述するスコープを宣言しcontractます。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {

}

果物を保持する配列を作成します。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {
  string[] myFruits;
}

これはプライベート修飾子を持つ文字列配列です。つまり、コントラクトの外部からアクセスできないため、値を直接変更することはできません。

次に、新しい値を追加する関数を作成します。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {
  string[] myFruits;

  function addFruit(string memory fruitName) public {
      myFruits.push(fruitName);
  }
}

addFruit文字列をパラメータとして受け入れる、という関数を作成しましたfruitName。これはパブリックとして宣言されているため、UIまたはターミナルから呼び出すことができます。関数本体では、値を配列にプッシュするだけです。

値を更新します。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {
  string[] myFruits;

  function addFruit(string memory fruitName) public {
      myFruits.push(fruitName);
  }

  function updateFruit(uint fruitIndex, string memory newFruitName) public returns (bool) {
      if(myFruits.length > fruitIndex){
          myFruits[fruitIndex] = newFruitName;
          return true;
      }
      return false;
  }
}

updateFruitfruitIndex2つの引数とを受け入れnewFruitName、ブール値を返します。これは次のように機能します。インデックスが配列の範囲外の場合は、を返しますfalse。それ以外の場合は、指定されたインデックスで新しく提供されたフルーツ名で配列の値を変更し、を返しtrueます。

次の手順は、削除機能を作成することです。

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {
  string[] myFruits;

  function addFruit(string memory fruitName) public {
      myFruits.push(fruitName);
  }

  function updateFruit(uint fruitIndex, string memory newFruitName) public returns (bool) {
      if(myFruits.length > fruitIndex){
          myFruits[fruitIndex] = newFruitName;
          return true;
      }
      return false;
  }

  function deleteFruit(uint fruitIndex) public returns (bool) {
      if(myFruits.length > fruitIndex){
          for(uint i=fruitIndex; i < myFruits.length-1; i++){
              myFruits[i] = myFruits[i+1];
          }

          myFruits.pop();

          return true;
      }
      return false;
  }
}

ここでは、インデックスの範囲外条件をチェックしてから、値を指定されたインデックスの次の値に置き換えることで配列を更新しています。このように、提供されたインデックスの値は失われます。最後に、最後の値を取り出して返しtrueます。

最後のステップは、配列を返すことです。配列のすべての値を読み取るには:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Fruits {
  string[] myFruits;

  function addFruit(string memory fruitName) public {
      myFruits.push(fruitName);
  }

  function updateFruit(uint fruitIndex, string memory newFruitName) public returns (bool) {
      if(myFruits.length > fruitIndex){
          myFruits[fruitIndex] = newFruitName;
          return true;
      }
      return false;
  }

  function deleteFruit(uint fruitIndex) public returns (bool) {
      if(myFruits.length > fruitIndex){
          for(uint i=fruitIndex; i < myFruits.length-1; i++){
              myFruits[i] = myFruits[i+1];
          }

          myFruits.pop();

          return true;
      }
      return false;
  }

  function getFruits() public view returns (string[] memory) {
      return myFruits;
  }
}

Truffleを使用したスマートコントラクトのコンパイル

スマートコントラクトのコーディングが完了したので、Truffleを使用してコンパイルします。ただし、最初に移行ファイルを作成して、これをチェーンに移行することをTruffleに示す必要があります。

フォルダをチェックインすると、migration2つのJavaScriptファイルが見つかります。

それぞれ番号で始まるので、3番目のファイルは3で始まります。コードはほぼ標準です。それ2_deploy_contractsは:

var SimpleStorage = artifacts.require("./SimpleStorage.sol");

module.exports = function(deployer) {
  deployer.deploy(SimpleStorage);
};

移行ファイルを追加しましょう3_fruits_contracts

var FruitsList = artifacts.require("./Fruits.sol");

module.exports = function(deployer) {
  deployer.deploy(FruitsList);
};

フルーツコントラクトをコンパイルして移行する準備が整いました。ターミナルに移動し、以下を実行します。

> truffle develop

このコマンドは、トリュフコンソールを起動します。また、チェーンネットワーク、アカウント、ニーモニックなどの情報も表示されます。

Ganacheはデフォルトで10個のアカウントを提供します。彼らはあなたのために異なります。これらの秘密鍵は、この記事のすべての訪問者に表示されるため、ライブチェーンでは使用しないでください。つまり、誰でもこれらのアカウントにアクセスできます。

次に、次のコマンドを使用してコントラクトをコンパイルします。

> compile

ファイルが作成されてclient/src/contractsいるかどうかを確認できます。Fruits.json

次のコマンドを使用して、コンパイルされたファイルをチェーンに移行できます。

> migrate

これにより、3つのスマートコントラクトすべてがチェーンに移行されます。



最後に、私たちのアプリケーションはイーサリアムチェーン上にあります。ガス料金に0.00153イーサを費やし、トランザクションが最初のアカウントから発生したことがわかります。デフォルトでは、常に最初のアカウントが使用されます。さまざまな操作ができるようになりました。

果物のリストを取得する

Web3.jsを使用して、さまざまな値に反応して書き込むことができます。まず、コントラクトのインスタンスを変数に格納しましょう。

let instance = await Fruits.deployed()

awaitブロックチェーン内のすべてが非同期であり、promiseを返すため、使用しています。

次に、このインスタンスを使用して配列を取得します。

> let fruits = instance.getFruits()
undefined
> fruits
[]

現在、fruits配列には値がないため、空の配列が返されます。

リストに果物を追加する

いくつかの果物を追加しましょう:

> let result = await instance.addFruit("Apple")
undefined

resultトランザクションを保持します。すべての読み取り操作は無料ですが、ブロックチェーンの変更につながる操作にはガス料金がかかることを忘れないでください。この操作は、配列に値を追加し、データを変更します。したがって、トランザクションとして記録されます。

これで、配列を再度読み取って内容を確認できます。

リストにさらにいくつかの果物を追加しましょう。

> await instance.addFruit("Mango")
> await instance.addFruit("Banana")
> await instance.addFruit("Orange")
> await instance.addFruit("Guava")
> await instance.addFruit("Pineapple")
> await instance.addFruit("Water Melon")
> await instance.addFruit("Papaya")
> await instance.addFruit("Strawberry")

これらすべての操作にはEtherのコストがかかることを忘れないでください。一度に複数の果物の値を受け入れるための関数をコントラクトに作成することで、手数料を節約できます。

今すぐ配列を読んでください:

果物の名前を更新する

上の画像で、「Guava」のつづりを「Guavva」と間違えたことがわかります。updateFruit関数を使って修正しましょう。インデックスと新しい値を受け入れます。インデックスは4です。

> await instance.updateFruit(4, "Guava")

今すぐ配列を読んでみましょう:

スペルは正常に修正されました。

果物の名前を削除する

最後の操作は、値を削除することです。

> await instance.deleteFruit(4)

値を読み取ります。

ご覧のとおり、「Guava」アイテムはリストから削除されています。

結論

スマートコントラクトを作成してブロックチェーンにデプロイするのは楽しくて強力です。これは、従来のプログラミングからの新しい視点を提供します。これらの手法を使用して、オンライン投票、デジタルバンク、ウォレット、オークションなど、あらゆる種類のアプリケーションを作成できます。

このチュートリアルでは、スマートコントラクトを作成してローカルチェーンにデプロイする方法を示しました。これで、イーサリアムのテストネットワークにデプロイしてみることができます。

一度に複数のフルーツを追加してトランザクションコストを節約するなど、より多くの機能を導入することで、現在のアプリを改善できます。また、ユニークな果物のみを許可するようにチェックを入れることもできます。配列の代わりに、マッピングを使用してみてください。

ハッピーコーディング! 

出典:https ://blog.logrocket.com/truffle-suite  

#truffle #ethereum #web3