Truffle は ethereum スマートコントラクトのコンパイル、マイグレーション、テストを行うためのフレームワークです。
Truffle は npm を使ってインストールしますので、事前に npm をインストールしてください。
また、ethereum ブロックチェーンも使用しますので ethereumブロックチェーンの構築(Ganache編) を参考に Ganache をインストールしてください。
> npm install -g truffle> mkdir my_project
> cd my_project
> truffle init
Starting init...
================
> Copying project files to C:\Users\shinobu\NoNameSeminer\ethereum\my_project
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生成されたファイルを確認してみます。
> tree /f
ボリューム シリアル番号は EEAF-D230 です
C:.
│ truffle-config.js
│
├─contracts
│ Migrations.sol
│
├─migrations
│ 1_initial_migration.js
│
└─test
.gitkeep各ファイルとディレクトリの説明。
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-cli, 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: 7545, // Standard Ethereum port (default: none)
network_id: "*", // Any network (default: none)
},Ganache を起動し「NEW WORKSPACE」をクリックします。

「ADD PROJECT」をクリックし、先ほど作成した「truffle-config.js」を選択します。


これで Ganache と Truffle の連携設定は完了です。「SAVE WORKSPACE」をクリックしてください。

> truffle console
truffle(development)>truffle(development)> truffle create contract Counter
truffle(development)>上記のコマンドで constracts ディレクトリの中に Counter.sol ファイルが生成されます。
エディタで Counter.sol を開き、以下のように編集してください。
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
contract Counter {
uint public count;
// Function to get the current count
function get() public view returns (uint) {
return count;
}
// Function to increment count by 1
function inc() public {
count += 1;
}
// Function to decrement count by 1
function dec() public {
count -= 1;
}
}truffle(development)> truffle compile
Compiling your contracts...
===========================
> Compiling .\contracts\Counter.sol
> Compiling .\contracts\Counter.sol
> Compiling .\contracts\Migrations.sol
> Artifacts written to C:\Users\shinobu\NoNameSeminer\ethereum\my_project\build\contracts
> Compiled successfully using:
- solc: 0.8.13+commit.abaa5c0e.Emscripten.clang
truffle(development)>Counter コントラクトをデプロイするためのマイグレーションファイルを作成します。
truffle(development)> truffle create migration Counter
truffle(development)>上記のコマンドで migrations ディレクトリの中に nnnnnnnn_counter.js ファイルが生成されます。
ファイルの以下のように書き換えて、Counter コントラクトをデプロイするように設定します。
const Counter = artifacts.require("Counter");
module.exports = function(_deployer) {
// Use deployer to state migration tasks.
_deployer.deploy(Counter)
};truffle(development)> truffle migrate
Compiling your contracts...
===========================
> Compiling .\contracts\Counter.sol
> Compiling .\contracts\Migrations.sol
> Artifacts written to C:\Users\shinobu\NoNameSeminer\ethereum\my_project\build\contracts
> Compiled successfully using:
- solc: 0.8.13+commit.abaa5c0e.Emscripten.clang
Starting migrations...
======================
> Network name: 'development'
> Network id: 5777
> Block gas limit: 6721975 (0x6691b7)
1_initial_migration.js
======================
Replacing 'Migrations'
----------------------
> transaction hash: 0x09353f6ea3c2ce57acf8de3a9c2c1110fb2abfeea6d51d896477509d6e6edc6a
> Blocks: 0 Seconds: 0
> contract address: 0x9864601fA497E29d85720c336b15267Ff0a89386
> block number: 1
> block timestamp: 1651037552
> account: 0x12C1B9B5152b14CE5af7A83947971108Dc89e54D
> balance: 99.99502292
> gas used: 248854 (0x3cc16)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.00497708 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.00497708 ETH
1651036112_counter.js
=====================
Replacing 'Counter'
-------------------
> transaction hash: 0x45b148c06609f587e5636a17a088f6685fc2e05603aed75a54bfcf01ba881129
> Blocks: 0 Seconds: 0
> contract address: 0x852560406282C788aeF29AbD5A9313588d86c3dB
> block number: 3
> block timestamp: 1651037554
> account: 0x12C1B9B5152b14CE5af7A83947971108Dc89e54D
> balance: 99.99086736
> gas used: 165265 (0x28591)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.0033053 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.0033053 ETH
Summary
=======
> Total deployments: 2
> Final cost: 0.00828238 ETH
truffle(development)>Counter コントラクトを呼び出すためのインスタンスを取得する。
truffle(development)> let counter = await Counter.deployed()
undefined
truffle(development)>Counter コントラクトの get を呼び出す。
truffle(development)> counter.get()
BN { negative: 0, words: [ 0, <1 empty item> ], length: 1, red: null }
truffle(development)>:!: 「BN」は「BigNumber」という意味です。後々、テスト等で値の比較をするときに int とは扱いが変わってきますので、覚えておいてください。
Counter コントラクトの inc を呼び出す。
truffle(development)> counter.inc()
{
tx: '0x10e87f126ce0934123624a8bd0d9c70a7d2d492fd1ade783646e828ccad6ad42',
receipt: {
transactionHash: '0x10e87f126ce0934123624a8bd0d9c70a7d2d492fd1ade783646e828ccad6ad42',
transactionIndex: 0,
blockHash: '0xc95665ead9fae2045cff12ba600d778a99454fbcdfcafe257f6c5dee61f76917',
blockNumber: 5,
from: '0x12c1b9b5152b14ce5af7a83947971108dc89e54d',
to: '0x852560406282c788aef29abd5a9313588d86c3db',
gasUsed: 42229,
cumulativeGasUsed: 42229,
contractAddress: null,
logs: [],
status: true,
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
rawLogs: []
},
logs: []
}
truffle(development)>もう一度、Counter コントラクトの get を呼び出す。(値が0から1になっている)
truffle(development)> counter.get()
BN { negative: 0, words: [ 1, <1 empty item> ], length: 1, red: null }
truffle(development)>truffle(development)> truffle create test SimpleCounterTest
truffle(development)>上記のコマンドで test ディレクトリの中に simple_counter_test.js ファイルが生成されます。
エディタで simple_counter_test.js を開き、以下のように編集してください。
const Counter = artifacts.require("Counter");
/*
* uncomment accounts to access the test accounts made available by the
* Ethereum client
* See docs: https://www.trufflesuite.com/docs/truffle/testing/writing-tests-in-javascript
*/
contract("SimpleCounterTest", function (/* accounts */) {
it("should assert true", async function () {
await Counter.deployed();
return assert.isTrue(true);
});
it("Counter inc", async function () {
let counter = await Counter.deployed();
let before = await counter.get();
await counter.inc();
let after = await counter.get();
// before and after is BN(BigNumber)
return assert.equal(after.toNumber(), before.toNumber() + 1);
});
it("Counter dec", async function () {
let counter = await Counter.deployed();
let before = await counter.get();
await counter.dec();
let after = await counter.get();
// before and after is BN(BigNumber)
return assert.equal(after.toNumber(), before.toNumber() - 1);
});
});truffle(development)> truffle test
Using network 'development'.
Compiling your contracts...
===========================
> Compiling .\contracts\Counter.sol
> Compiling .\contracts\Migrations.sol
> Artifacts written to C:\Users\shinobu\AppData\Local\Temp\test--15628-Lt5184Kc9NTX
> Compiled successfully using:
- solc: 0.8.13+commit.abaa5c0e.Emscripten.clang
Contract: SimpleCounterTest
√ should assert true (55ms)
√ Counter inc (1361ms)
√ Counter dec (1419ms)
3 passing (3s)
truffle(development)>