LoginSignup
10
3

More than 5 years have passed since last update.

Ethereum/Solidityのテスト&デプロイ

Posted at

Ethereum界隈が楽しそうなので、Solidityの開発環境を整えた。
mochaとganache-cliを使ったローカルテストと、truffle-hdwallet-providerとinfura.ioを使ったデプロイ。

利用するライブラリのバージョンなどは後述するpackage.json参照。作業環境のディレクトリ構成は以下の通り。

.
├── compile.js
├── contracts
│   └── Calc.sol
├── deploy.js
├── package.json
└── test
    └── Calc.test.js

①アカウント等を準備

Metamaskをインストール。
KovanやRopstenの Test NetのfaucetからEtherをゲット。
Hi-EtherのSlackにも参加させて頂きました。

②コントラクトを実装

まずはSolidityで簡単なコントラクトを実装。remix便利だ。

contracts/Calc.sol
pragma solidity ^0.4.17;

contract Calc{
    int32 public num;

    function Calc(int32 initialNum) public{
        num = initialNum;
    }

    function setNum(int32 newNum) public{
        num = newNum;
    }

    function sqNum() public returns (int32){
        return num * num;
    }
} 

③ローカルテスト

環境はmacOS version10.12.3、npm 5.6.0、node v9.6.1で、package.jsonは以下の通り。

package.json
{
  "name": "calc",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "mocha"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "ganache-cli": "^6.0.3",
    "mocha": "^5.0.1",
    "solc": "^0.4.20",
    "truffle-hdwallet-provider": "0.0.3",
    "web3": "^1.0.0-beta.26"
  }
}

Solidityコンパイルは以下の通り行う。

compile.js
const path = require('path');
const fs = require('fs');
const solc = require('solc');

const calcPath = path.resolve(__dirname, 'contracts', 'Calc.sol');
const source = fs.readFileSync(calcPath, 'utf8');

module.exports = solc.compile(source, 1).contracts[':Calc'];

プロバイダーはganacheを使ってテストプログラムを下記のように作成。

test/Calc.test.js
const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const provider = ganache.provider();
const web3 = new Web3(provider);
const {interface, bytecode } = require('../compile');

let accounts;
let calc;

beforeEach(async () => {
    accounts = await web3.eth.getAccounts();
    calc = await new web3.eth.Contract(JSON.parse(interface))
        .deploy({data: bytecode, arguments: [7]})
        .send({from: accounts[0], gas: '1000000'});
    calc.setProvider(provider);
});

describe('Calc', () => {
    it('deploys a contract', () => {
        assert.ok(calc.options.address);
    });
    it('has a default number', async () => {
        const num = await calc.methods.num().call();
        assert.equal(num, 7);
    });
    it('can change the number', async () => {
        await calc.methods.setNum(3).send({from: accounts[0]});
        const num = await calc.methods.num().call();
        assert.equal(num, 3);
    });
    it('can square the number', async () => {
        const squaredNum = await calc.methods.sqNum().call();
        assert.equal(squaredNum, 49);
    });
});

npm run testでテスト完了!

④デプロイ

infura.ioのAPI とtruffle-hdwallet-providerを使ってデプロイ。

deploy.js
const HDWalletProvider = require('truffle-hdwallet-provider');
const Web3 = require('web3');
const {interface, bytecode } = require('./compile');

const provider = new HDWalletProvider(
    'xxx xxx xxx  xxx xxx xxx  xxx xxx xxx  xxx xxx xxx',
    'https://kovan.infura.io/xxxxxxxxxxxxxxxxxxxx'
);
const web3 = new Web3(provider);

const deploy = async () => {
    const accounts = await web3.eth.getAccounts();
    console.log("account: ", accounts[0]);

    const result = await new web3.eth.Contract(JSON.parse(interface))
        .deploy({ data: bytecode, arguments: [7]})
        .send({ gas: '1000000', from: accounts[0]});
    console.log("address: ", result.options.address);
};
deploy();

node deploy.jsでデプロイしたら、トランザクションアドレスを表示するので、あとはremixなどから実際に動かしたりなどご自由に楽しむ感じで。

参考資料

Stephen Grider, “Ethereum and Solidity: The Complete Developer's Guide”

10
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
3