見出し画像

【Solidity】 Walletでの送金を行う

環境セットアップ

MacOS 21.6.0
Visual Studio Code 1.73.1
Solidity 0.8.0
Homebrew 3.6.20
Node.js v18.12.1
npm(Node Package Manager)8.19.2


作業ログ


設定例

Node.jsとnpmのインストール

Homebrewを使用してインストール。Homebrewは、Macでソフトウェアをインストールするためのパッケージマネージャー。

Homebrewのインストール

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew -v
-----------------------------------------------------------
# 出力例
Homebrew 3.3.12
Homebrew/homebrew-core (git revision 5dd44; last commit 2023-04-08)
Homebrew/homebrew-cask (git revision 6d9d6; last commit 2023-04-08)


Node.jsとnpmのインストール

brew install node
node -v
npm -v
-----------------------------------------------------------
# 出力例
v16.14.0
8.3.1


TruffleとGanache CLIをインストール

npm(Node Package Manager)を使用して、2つの主要なEthereum開発ツールであるTruffleとGanache CLIをグローバルにインストールする。

npm install -g truffle ganache-cli
  1. truffle: Truffleは、Ethereum用の開発フレームワーク。スマートコントラクトのコンパイル、デプロイ、テストのための機能を提供しており、開発プロセスを効率化。また、JavaScriptによるスマートコントラクトの抽象化により、コード内でEthereumのコントラクトを簡単に操作できる。

  2. ganache-cli: Ganache CLI(以前はTestRPCとして知られていた)は、Ethereum用のコマンドラインツールで、開発用のローカルブロックチェーンを作成して実行するために使用されます。Ganache CLIは、開発中にリアルタイムで取引を確認し、デバッグ情報を取得することができる。


ディレクトリの作成

プロジェクトの基本構造を作成する。

mkdir wallet-transfer
cd wallet-transfer


Truffleプロジェクトの初期化

truffle init
-----------------------------------------------------------
# 出力例
Starting init...
================

> Copying project files to /Users/ooekenfutoshi/wallet-transfer

Init successful, sweet!

Try our scaffold commands to get started:
  $ truffle create contract YourContractName # scaffold a contract
  $ truffle create test YourTestName         # scaffold a test

http://trufflesuite.com/docs


Solidityファイルの作成

wallet-transferディレクトリにある、contractsディレクトリ内にWallet.solという名前で新しいファイルを作成。ウォレット間で送金を実行するための簡単なスマートコントラクト。

vi contracts/Wallet.sol
-----------------------------------------------------------
# 以下を追加(最新のものかは確認してください)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Wallet {
    function transfer(address payable _to, uint256 _amount) public payable {
        require(msg.value == _amount, "Amount sent does not match the requested amount.");
        _to.transfer(_amount);
    }
}


コントラクトをコンパイル

wallet-transferディレクトリにある、migrationsディレクトリに新しいJavaScriptファイル2_deploy_wallet.jsを作成し、次のコードを追加。コントラクトのデプロイ準備を行う。

vi contracts/2_deploy_wallet.js
-----------------------------------------------------------
const Wallet = artifacts.require("Wallet");

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


ローカルのEthereumネットワークを起動

デフォルトでは、127.0.0.1のアドレスと7545のポートで実行される。

ganache-cli
-----------------------------------------------------------
# 出力例
Ganache CLI v6.12.2 (ganache-core: 2.13.2)

Available Accounts
==================
(0) 0x4286B48977B4C3dF67980809f0DA87222f2eCE80 (100 ETH)
(1) 0xc96F09907178d6bF371E8c91eF6c67E1FE07CA53 (100 ETH)
(2) 0x54Af8387E4c37789E97655E07B599cAAAC856014 (100 ETH)
(3) 0x451ba463710C4b2b864D6aBFb571C12A94498A97 (100 ETH)
(4) 0xFD3d711cAb0D873246bEe9C8B7c9a72ee752a608 (100 ETH)
(5) 0x8BC97e49965fdFf9D9FaaE029228788E33157CF1 (100 ETH)
(6) 0xa4B653bB1a16439779c58f51875Aabf46E93D33B (100 ETH)
(7) 0x6012D719650431EE9BF34523aad283d96DA43B94 (100 ETH)
(8) 0x997Eb86eaF60dFE24f539A6d79f0aD0420D95270 (100 ETH)
(9) 0x006e4362e19144F2a44519F0787De3Fcb5cCa1e3 (100 ETH)

Private Keys
==================
(0) 0x4a086f8a078fc1b76680186eb5b180b6d9af0b5891e75c57a854305ed876d462
(1) 0x6e7966119f81cc0fdb295086168baefcbb46e70023d2051b1bfd8277dd916a13
(2) 0x25f23aa52e99b22f4a04f93b267e1da623f6cf25c3a1436ce2ae7b5c1dd4f0f5
(3) 0xaeef38c9fcc6ec656a054ebc4e9768265fb5a24e77b7c34312b8a03e69b18856
(4) 0x933db84a4f98e67aee4d2af47d021d56f70cd6235363c962b13585fb5379bef4
(5) 0x8a71c6cebe39864fe710d0256689b3a877509dcd8fb35557d629156a68dfcdb5
(6) 0xeaa8754dc9c0cc9878c766ab784c57d7fe98a3bce2905c07d7f29481c0629374
(7) 0x13cbf147c119added3788eb5616b18c8dd76cdee9442f6abd18d90e65c038933
(8) 0xb5c5d231b154273dde65e758553d3a92b6258b7d8dbc39953df22881a1b10b40
(9) 0xc7dc1ef693cb4843d42ea772cd33d7ebb1fd7ec4133565a4b9c7891bf95885d5

HD Wallet
==================
Mnemonic:      know electric lunch nest glance heart erosion kite quality upgrade antique gun
Base HD Path:  m/44'/60'/0'/0/{account_index}

Gas Price
==================
20000000000

Gas Limit
==================
6721975

Call Gas Limit
==================
9007199254740991

Listening on 127.0.0.1:8545
eth_blockNumber
net_version
eth_accounts
eth_getBlockByNumber
eth_accounts
・
・
・


コントラクトをコンパイルおよびデプロイ

新しいターミナルウィンドウで、先ほどのwallet-transferディレクトリに戻り、truffleを使用してコントラクトをコンパイルおよびデプロイします。

truffle compile             
-----------------------------------------------------------
# 出力例
Compiling your contracts...
===========================
> Compiling ./contracts/Wallet.solsolc-bin. Attempt #1
> Artifacts written to /Users/ooekenfutoshi/Desktop/wallet-transfer/build/contracts
> Compiled successfully using:
   - solc: 0.8.19+commit.7dd6d404.Emscripten.clang
truffle migrate 
-----------------------------------------------------------
# 出力例
Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
> Something went wrong while attempting to connect to the network at http://127.0.0.1:7545. Check your network configuration.
CONNECTION ERROR: Couldn't connect to node http://127.0.0.1:7545.
Truffle v5.8.1 (core: 5.8.1)
Node v18.12.1

エラーが出たとき

Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
> Something went wrong while attempting to connect to the network at http://127.0.0.1:7545. Check your network configuration.
CONNECTION ERROR: Couldn't connect to node http://127.0.0.1:7545.
Truffle v5.8.1 (core: 5.8.1)

上記のようなエラーが出たときは、Ganacheで起動しているポートとの相違がある可能性があるので確認する必要がある。
truffle-config.jsファイルを開くとコメントアウトされている下記の記載があるので、これを取り除く。

networks: {
    // Useful for testing. The `development` name is special - truffle uses it by default
    // if it's defined here and no other network is specified at the command line.
    // You should run a client (like ganache, geth, or parity) in a separate terminal
    // tab if you use this network and you must also set the `host`, `port` and `network_id`
    // options below to some value.
    //
    // development: {
    //  host: "127.0.0.1",     // Localhost (default: none)
    //  port: 8545,            // Standard Ethereum port (default: none)
    //  network_id: "*",       // Any network (default: none)
    // },
    //
    // An additional network, but with some advanced options…
    // advanced: {
    //   port: 8777,             // Custom port
    //   network_id: 1342,       // Custom network
    //   gas: 8500000,           // Gas sent with each transaction (default: ~6700000)
    //   gasPrice: 20000000000,  // 20 gwei (in wei) (default: 100 gwei)
    //   from: <address>,        // Account to send transactions from (default: accounts[0])
    //   websocket: true         // Enable EventEmitter interface for web3 (default: false)
    // },
    //
    // Useful for deploying to a public network.
    // Note: It's important to wrap the provider as a function to ensure truffle uses a new provider every time.

↓↓↓↓↓↓=================================================================================

networks: {
    // Useful for testing. The `development` name is special - truffle uses it by default
    // if it's defined here and no other network is specified at the command line.
    // You should run a client (like ganache, geth, or parity) in a separate terminal
    // tab if you use this network and you must also set the `host`, `port` and `network_id`
    // options below to some value.
    //
     development: {
      host: "127.0.0.1",     // Localhost (default: none)
      port: 8545,            // Standard Ethereum port (default: none)
      network_id: "*",       // Any network (default: none)
     },
    //



コントラクトをインタラクト

Truffleコンソールを使用してコントラクトをインタラクトする。

truffle console    
-----------------------------------------------------------
# 出力例
truffle(development)> 


Walletコントラクトのインスタンスを取得

Truffleコンソールが開いたら、次のコマンドを実行する。

truffle(development)> const wallet = await Wallet.deployed()
undefined

Truffleプロジェクトでスマートコントラクトがデプロイされた後、デプロイされたスマートコントラクトのインスタンスを取得するコード。

awaitキーワードを使ってWallet.deployed()を呼び出すことで、デプロイされたスマートコントラクトのインスタンスが非同期的に取得される。


送金の準備

const accounts = await web3.eth.getAccounts()
const sender = accounts[0]
const receiver = accounts[1]
const amount = web3.utils.toWei('0.1', 'ether')
-----------------------------------------------------------
# 出力例
truffle(development)> const accounts = await web3.eth.getAccounts()
undefined
truffle(development)> const sender = accounts[0]
undefined
truffle(development)> const receiver = accounts[1]
undefined
truffle(development)> const amount = web3.utils.toWei('0.1', 'ether')
undefined
  • const accounts = await web3.eth.getAccounts(): web3インスタンスを使って、接続されたEthereumノード上のアカウントのリストを非同期的に取得。

  • const sender = accounts[0]: アカウントリストの最初のアカウント(accounts[0])を送信者(sender)として設定。

  • const receiver = accounts[1]: アカウントリストの2番目のアカウント(accounts[1])を受信者(receiver)として設定。

  • const amount = web3.utils.toWei('0.1', 'ether'): 送金する金額をエーテル(Ether)単位からウェイ(Wei)単位に変換。これは、Ethereumネットワーク上で送金を行うための最小単位になる。


送金の実行

wallet.transfer関数を呼び出すことで、送金を実行。senderアカウントからreceiverアカウントへ0.1 ETHが送金される。

truffle(development)> await wallet.transfer(receiver, amount, { from: sender, value: amount })
-----------------------------------------------------------
# 出力例
{
  tx: '0xf2d4f82dde6dbd4a010909cd299f4edc657647eeda0917969e27323a5d53dfaa',
  receipt: {
    transactionHash: '0xf2d4f82dde6dbd4a010909cd299f4edc657647eeda0917969e27323a5d53dfaa',
    transactionIndex: 0,
    blockHash: '0x4ae07c476509f48e70bd2f2398ab541769b43874bd7641c2be1cd145cd27bb27',
    blockNumber: 2,
    from: '0x4286b48977b4c3df67980809f0da87222f2ece80',
    to: '0x37ff123f96ea63268469382d4f7577bd72bfcc5c',
    gasUsed: 29740,
    cumulativeGasUsed: 29740,
    contractAddress: null,
    logs: [],
    status: true,
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    rawLogs: []
  },
  logs: []
}
  1. receiver: 送金を受け取るアカウントのアドレス。

  2. amount: ウェイ単位で表された送金額。

  3. { from: sender, value: amount }: トランザクションオブジェクト。このオブジェクトには、送信者アカウント(from)および送金額(value)が含まれています。

このコードは、senderアカウントからreceiverアカウントへamountウェイを送金する。


送金の確認

送金が正常に行われたことを確認するために、各アカウントの残高を取得

const senderBalance = await web3.eth.getBalance(sender)
const receiverBalance = await web3.eth.getBalance(receiver)
console.log('Sender balance:', web3.utils.fromWei(senderBalance, 'ether'))
console.log('Receiver balance:', web3.utils.fromWei(receiverBalance, 'ether'))
-----------------------------------------------------------
# 出力例
truffle(development)> const senderBalance = await web3.eth.getBalance(sender)
undefined
truffle(development)> const receiverBalance = await web3.eth.getBalance(receiver)
undefined
truffle(development)> console.log('Sender balance:', web3.utils.fromWei(senderBalance, 'ether'))
Sender balance: 99.89559554
undefined
truffle(development)> console.log('Receiver balance:', web3.utils.fromWei(receiverBalance, 'ether'))
Receiver balance: 100.1
  • const senderBalance = await web3.eth.getBalance(sender): 送信者アカウントの残高を取得。

  • const receiverBalance = await web3.eth.getBalance(receiver): 受信者アカウントの残高を取得。

  • console.log('Sender balance:', web3.utils.fromWei(senderBalance, 'ether')): 送信者アカウントの残高をEther単位で表示。

  • console.log('Receiver balance:', web3.utils.fromWei(receiverBalance, 'ether')): 受信者アカウントの残高をEther単位で表示。

よろしければサポートお願いします!よりいい情報を発信します。