ブロックチェーン開発メモ ~Truffle デプロイ編~
やりたいこと
Ethereum + Solidityでスマートコントラクトを実装したい。
前回: ブロックチェーン開発メモ ~Ethereum2.0 ネットワーク同期編~
Truffle サンプルプロジェクトを作る
主に https://trufflesuite.com/docs/truffle/quickstart/ に沿って行う。
まずはプロジェクトを作るところから始める。
Truffleにはサンプルプロジェクトが用意されているので、まずはそれを試してみる。
$ mkdir ./truffle-test1
$ cd ./truffle-test1
$ truffle unbox metacoin ./
コマンド実行後、指定したディレクトリにプロジェクトファイルが出力されるので、truffle-config.js
を開いてみる。
module.exports = {
// ~~
compilers: {
solc: {
version: "0.8.13", // Fetch exact version from solc-bin
}
}
};
solcjs
のバージョンが0.8.13
を示しているので、とりあえず自身の環境もそれに合わせておく。
$ npm uninstall -g solc
$ npm install -g solc@0.8.13
$ solcjs --version
テストを実行する
$ truffle test
Compiling your contracts...
===========================
✓ Fetching solc version list from solc-bin. Attempt #1
✓ Downloading compiler. Attempt #1.
> Compiling ./contracts/ConvertLib.sol
> Compiling ./contracts/MetaCoin.sol
> Compiling ./test/TestMetaCoin.sol
> Artifacts written to /tmp/test--4331-z5Y9Kzcsev39
> Compiled successfully using:
- solc: 0.8.13+commit.abaa5c0e.Emscripten.clang
TestMetaCoin
✔ testInitialBalanceUsingDeployedContract (78ms)
✔ testInitialBalanceWithNewMetaCoin (54ms)
Contract: MetaCoin
✔ should put 10000 MetaCoin in the first account (49ms)
✔ should call a function that depends on a linked library (60ms)
✔ should send coin correctly (113ms)
5 passing (4s)
コンパイルする
$ truffle compile
Compiling your contracts...
===========================
> Compiling ./contracts/ConvertLib.sol
> Compiling ./contracts/MetaCoin.sol
> Artifacts written to /home/vagrant/Desktop/projects/block-chain-test/build/contracts
> Compiled successfully using:
- solc: 0.8.13+commit.abaa5c0e.Emscripten.clang
./build/contracts
にJSONが出力される。
ローカルにデプロイする
スマートコントラクトをデプロイするには、メインネットやテストネットといったブロックチェーンにデプロイする必要があるが、Truffle
にはテスト用にローカルで使用できるブロックチェーンが用意されている。
Truffle
を使ってメインネットやテストネットにデプロイする方法は、またどこかで記載予定。
$ truffle develop
Truffle Develop started at http://127.0.0.1:9545/
Accounts:
(0) 0x2f8ecedd71ca2482c4a6466512095adb0e809720
(1) 0xddd0a152a9dba2d5d0141a37d31be8139739ac39
(2) 0xd23380e697c59f1d6bc37a8865218e385e769fe8
(3) 0x751c2b2c339c746d601e791fe0b17bef99962652
(4) 0x791be6829f14577f2a3b77ccf418a50aee88d89b
(5) 0x49b12ccbda7e6b57b6d48c490bd9d7af6ce30954
(6) 0xc837cffc2f940effb8418ea2b74fed21d59492ee
(7) 0xc44c095176f552b4cc0114d756b14dae5b67dc9d
(8) 0x064ce3aa53b87ba1b997c266066c626d699f7f2d
(9) 0xab2f5ca2b13d1804af7f29b87800ca0a5ad4d6a2
Private Keys:
(0) 99bb685fffdb298485b5c56e4c700c20341e7eda7af925a3bd132ba54f7afc98
(1) 96daf889b560e5c501da62d49a881140cd07c18c61372ebe851abde00a7c20ae
(2) 02a63d480401ed6defea76532a8673f59d550e7e0fab987f435c5e0754caf199
(3) 77ef7d76d40e11f90e8e85c4ed191da202155d2e5ed8f63c92a98cadad3ff525
(4) 4b627a7435bae4361e610ab40d41e237b17a375864b0671df6e467821b85fc8d
(5) da26caa0d051cf96f23de7f909eadca04e285d81fc1081094a9dec5adcc5e096
(6) 1a559ff31dfe7a4e7134682278f57c0485e47502c2adc04571f7bfc95e72c66c
(7) 0f1abdca38dfacd82bf0799eaac57d1215292a9269e64b0ace0289f1321d196d
(8) b9211d133ff2358af6c40b3a7fcc6711772fb4dc50de3e3112f79b6febda77ac
(9) 10116829a9e32ed98ad054fcbd846bc90d5cf3388c3f95f2fbcf0499dc68686f
Mnemonic: diagram naive such open soldier spice sound regret exact enter impose leopard
⚠️ Important ⚠️ : This mnemonic was created for you by Truffle. It is not secure.
Ensure you do not use it on production blockchains, or else you risk losing funds.
truffle(develop)>
migrate
コマンドを実行するだけで、ローカルのブロックチェーンにコンパイル⇒デプロイが行われる。
デプロイは ./migrations/1_deploy_contracts.js
の内容に従って実行される。
truffle(develop)> migrate
Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
Starting migrations...
======================
> Network name: 'develop'
> Network id: 5777
> Block gas limit: 6721975 (0x6691b7)
1_deploy_contracts.js
=====================
Deploying 'ConvertLib'
----------------------
> transaction hash: 0xeb5782ec5f3136636152f79b2c81fe3fe8f820dd0d41329b1caf09fd19d8d432
> Blocks: 0 Seconds: 0
> contract address: 0x8f769C476B551033d784f0052f02C5BAecC4618C
> block number: 1
> block timestamp: 1700673166
> account: 0x2f8eceDd71ca2482C4A6466512095AdB0E809720
> balance: 99.9994680865
> gas used: 157604 (0x267a4)
> gas price: 3.375 gwei
> value sent: 0 ETH
> total cost: 0.0005319135 ETH
Linking
-------
* Contract: MetaCoin <--> Library: ConvertLib (at address: 0x8f769C476B551033d784f0052f02C5BAecC4618C)
Deploying 'MetaCoin'
--------------------
> transaction hash: 0xf5d98a825a322a59b4eeca87cf9e3627d8c09251b2a6a19d0abd353d047fa5da
> Blocks: 0 Seconds: 0
> contract address: 0xFFF84424a081Eb11991F9BbBb21DBbC91aCC4a70
> block number: 2
> block timestamp: 1700673166
> account: 0x2f8eceDd71ca2482C4A6466512095AdB0E809720
> balance: 99.9981051633782056
> gas used: 416700 (0x65bbc)
> gas price: 3.270753832 gwei
> value sent: 0 ETH
> total cost: 0.0013629231217944 ETH
> Saving artifacts
-------------------------------------
> Total cost: 0.0018948366217944 ETH
Summary
=======
> Total deployments: 2
> Final cost: 0.0018948366217944 ETH
truffle(develop)>
ブロックチェーン上にデプロイ(トランザクション発行)するにはガス代がかかるが、ローカルのブロックチェーンなら開発用として無料で試せるのでぜひ活用していきたい。
Ganacheを使ってコントラクトを操作する
Ganacheで視覚的に情報を確認しながら、コントラクトを操作できる。
Truffleの設定を変更する
truffle-config.js
を開き、以下の様に変更する。
module.exports = {
~~~
networks: {
~~~
development: {
host: "127.0.0.1", // Localhost (default: none)
port: 7545, // Standard Ethereum port (default: none)
network_id: "*", // Any network (default: none)
},
~~~
};
Ganacheを起動する
まずは起動する。
設定から ADD PROJECT
を選択して、truffle-config.js
を指定。
再度デプロイする
改めてGanacheで確認できるようにデプロイする。
$ truffle migrate
Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
Starting migrations...
======================
> Network name: 'development'
> Network id: 5777
> Block gas limit: 6721975 (0x6691b7)
1_deploy_contracts.js
=====================
Replacing 'ConvertLib'
----------------------
> transaction hash: 0x4052df8cc37e31b2b2d5f04b004dfbb159272f5191e6dbd14004007e455a702f
> Blocks: 0 Seconds: 0
> contract address: 0xEB5b97ca8DAd9D8d5EfD4534f2FF698D7B7Facce
> block number: 1
> block timestamp: 1700675871
> account: 0xe8421bcd5E7092a51aA82900d001D5F86608bdCD
> balance: 99.999468208
> gas used: 157568 (0x26780)
> gas price: 3.375 gwei
> value sent: 0 ETH
> total cost: 0.000531792 ETH
Linking
-------
* Contract: MetaCoin <--> Library: ConvertLib (at address: 0xEB5b97ca8DAd9D8d5EfD4534f2FF698D7B7Facce)
Replacing 'MetaCoin'
--------------------
> transaction hash: 0x16b84bda682d1b3b6855894360ea9ca344efc03dc250c88fb8e9699811454e62
> Blocks: 0 Seconds: 0
> contract address: 0x33D1e2e14474a050dEb6B653Fa7721Fb057C1103
> block number: 2
> block timestamp: 1700675871
> account: 0xe8421bcd5E7092a51aA82900d001D5F86608bdCD
> balance: 99.998105632065943366
> gas used: 416594 (0x65b52)
> gas price: 3.270752661 gwei
> value sent: 0 ETH
> total cost: 0.001362575934056634 ETH
> Saving artifacts
-------------------------------------
> Total cost: 0.001894367934056634 ETH
Summary
=======
> Total deployments: 2
> Final cost: 0.001894367934056634 ETH
GanacheのTransactionsタブを確認すると、トランザクションの状況が確認できる。
コントラクトを操作する
Trrufleコンソールを開き、コントラクトを操作する。
$ truffle console
# MetaCoinコントラクトを保存
truffle(development)> let instance = await MetaCoin.deployed()
undefined
# アカウント一覧を保存
truffle(development)> let accounts = await web3.eth.getAccounts()
undefined
# コントラクトをデプロイしたアカウントのメタコイン残高を取得
truffle(development)> let balance = await instance.getBalance(accounts[0])
undefined
# 表示
truffle(development)> balance.toNumber()
10000
# イーサリアム換算でどれくらいかを取得
truffle(development)> let ether = await instance.getBalanceInEth(accounts[0])
undefined
# 表示(1メタコイン = 2イーサリアム)
truffle(development)> ether.toNumber()
20000
# 別アカウントに500メタコインを送信
truffle(development)> instance.sendCoin(accounts[1], 500)
{
tx: '0xd2e62d332a87100e15f6d9b8ebdfbca94d90f4ee49c552926492c9f17c4a102b',
receipt: {
transactionHash: '0xd2e62d332a87100e15f6d9b8ebdfbca94d90f4ee49c552926492c9f17c4a102b',
transactionIndex: 0,
blockNumber: 3,
blockHash: '0xee63b714688f82283256a4bc51584b4a86d4b3315749d9d7ff39c3f0704eda47',
from: '0xe8421bcd5e7092a51aa82900d001d5f86608bdcd',
to: '0x33d1e2e14474a050deb6b653fa7721fb057c1103',
cumulativeGasUsed: 52297,
gasUsed: 52297,
contractAddress: null,
logs: [ [Object] ],
logsBloom: '0x00008000001000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000002000008000000000000000000000000000020000000000080000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000',
status: true,
effectiveGasPrice: 3186350418,
type: '0x2',
rawLogs: [ [Object] ]
},
logs: [
{
address: '0x33D1e2e14474a050dEb6B653Fa7721Fb057C1103',
blockHash: '0xee63b714688f82283256a4bc51584b4a86d4b3315749d9d7ff39c3f0704eda47',
blockNumber: 3,
logIndex: 0,
removed: false,
transactionHash: '0xd2e62d332a87100e15f6d9b8ebdfbca94d90f4ee49c552926492c9f17c4a102b',
transactionIndex: 0,
id: 'log_fb3c9158',
event: 'Transfer',
args: [Result]
}
]
}
# 別アカウントのメタコイン残高を確認
truffle(development)> let received = await instance.getBalance(accounts[1])
undefined
truffle(development)> received.toNumber()
500
# コントラクトをデプロイしたアカウントのメタコイン残高を確認
truffle(development)> let newBalance = await instance.getBalance(accounts[0])
undefined
truffle(development)> newBalance.toNumber()
9500
以上。
Discussion