本記事は、『ConsenSys社のERC1400実装を動かす』を前編・後編に分けて掲載します。
(1)ERC1400を動かす為の環境構築を行います。
(2)コントラクトをブロックチェーンにデプロイします。
(3)デプロイしたコントラクトを操作して、セキュリティトークンの発行・移転・償還を実行し、またセキュリティトークンならではの機能を動かして体験できます。
Polymath社が実装したERC1400であるST-20の動作の解説については別記事で行っております。ぜひこちらも参照ください。(前編・後編)
サマリー
本記事では、『ConsenSys社のERC1400実装を動かす』の前編として、以下を実行していきます。
(1)ERC1400を動かす為の環境構築を行います。
(2)コントラクトをブロックチェーンにデプロイします。
参考
本記事は以下、ConsenSysのGitHubを参考にしています。
https://github.com/ConsenSys/ERC1400
環境構築
環境構築をしていきます。
前提事項
PC : Mac
OS : macOS High Sierra
homebrew(v1.6.7以上)がインストール済み
git : インストール済み
Node.jsとnpm
Ethereum関連のツールのダウンロードに使います。今回はNode v8.15.0、npm 6.4.1を使用します。
yarn
npm同様にパッケージ管理ツールです。yarn 1.17.3を利用しています。
Truffle
まずTruffleの5系が必要になります。ConsenSys社のGitHubでは、5.0.1が必要となっているので、インストールします。
$ npm install -g truffle@5.0.1
Truffleのインストールに成功すると、以下のコマンドでバージョンを確認できます。
ERC1400$truffle version
Truffle v5.0.1 (core: 5.0.1)
Solidity - 0.5.10 (solc-js)
Node v8.15.0
truffle-hdwallet-provider
ニーモニックに基づくユーザーのアドレスがトランザクションに署名する時に利用されるソフトです。
$ npm install truffle-hdwallet-provider
参考
https://www.npmjs.com/package/truffle-hdwallet-provider
ERC1400
今回使うERC1400の実装コードをインストールします。動作確認はこのERC1400のディレクトリ上で行います。
$ git clone https://github.com/ConsenSys/ERC1400.git
Ganache-CLI
Truffleに関係するツールで、イーサリアム開発のためのローカル環境用のブロックチェーンを提供してくれるツールです。GUI版とCLI版があり、後者を利用します。
$ npm install -g ganache-cli@6.7.0
参考 https://github.com/trufflesuite/ganache-cli
Web3.js
Ethereumブロックチェーン上のノードとローカルとの通信を可能にしているJavaScriptのライブラリです。バージョンはv1.0.0-beta.37を利用します。
$ npm install -g web3@1.0.0-beta.37
デプロイまでの動作
ターミナルを開いて、インストールしたリポジトリのERC1400までカレントディレクトを移動してくだい。
パッケージインストール
package.jsonからdependenciesをインストールします。少し時間がかかります。これで関連するツールのインストールができます。
$yarn install
Ganache-CLI起動
まずGanach-CLIを起動します。
$ganache-cli
成功すると以下のようになります。
Ganache CLI v6.7.0 (ganache-core: 2.8.0)
Available Accounts
==================
(0) 0xb508711F4C86EfB4A56337c4688ba671531Ecf76 (100 ETH)
(1) 0x026Cce23f9EdA4Aa5609fD4D7611Bcc421262503 (100 ETH)
(2) 0x497370c1128173564A29FBf77b23bF98cccf4F5E (100 ETH)
(3) 0x741FbFc15A515571D71123adbDc49EE115e3A92E (100 ETH)
(4) 0x4Bc0359E785FD0a05AB9EAF76541Cd2baE62d89E (100 ETH)
(5) 0xBA886a9B71b27a4A4481CCC06c75b4Ab65EB8e96 (100 ETH)
(6) 0x95B08F581183e2f89D65a19AeC5ce1100D37C73c (100 ETH)
(7) 0xDFc61dC4e42E55D23670D026f64d13E55ED9F4B7 (100 ETH)
(8) 0x593ea9C09C17f373aE0A2fDAb524c127f7FA2ac9 (100 ETH)
(9) 0xfab1C1d88665B4E6af01AfD10CEab76C6A9A1270 (100 ETH)
Private Keys
==================
(0) 0xe781795318528fe296c0e14ff730a16338d2e2571c684bd32e01b7e7cc1692a7
(1) 0xa7480a0b6deaf045715b9271a2a5858cc76298bbbd67fbf0568f6da1276673f6
(2) 0x8eaf34d23bbc91396cc228ddafd5358b1bf9b6ccde0978757fd89806d4253250
(3) 0x890593d5fec15ab02679a6d2468dc3de438877c6435d2364db77f834448704f2
(4) 0xd28502f93a242b92f93dc165d95ae028d6334eaa7df7d642c98e0b6ad21fce68
(5) 0x769e7dbc150aa0012bc62647dd57aacda133bd3396cece8d7cfe4c89ebe9c9a8
(6) 0x7a8ceaa651e5f1f317ffe3c3e6aae17a0e823052b06392db7298e89f3734ae49
(7) 0xbf7304b0f70b0621b216f0c2a61e5dda4cbd66e8dd64316e37077bdff229dc0b
(8) 0xc89e9ad3702d7d41413d77c803b149da6fa4197a73d1fdef20c0f091c7092111
(9) 0x6fdd8e802af6323ef2c3a3f6698d9f13cccf2edef1a90822de662e6582bd4bd4
HD Wallet
==================
Mnemonic: ritual bleak person auction slab correct entire paddle direct income purpose subject
Base HD Path: m/44'/60'/0'/0/{account_index}
Gas Price
==================
20000000000
Gas Limit
==================
6721975
Listening on 127.0.0.1:8545
上記よりアカウント、それに対応する秘密鍵等の情報がわかります。ここで注目してもらいたいのが、以下です。
Listening on 127.0.0.1:8545
Ganacheはポート番号8545を使っていることがわかります。なのでこれからERC1400をデプロイする時は、port番号8545に接続することになります。よってGitHubからインストールしてERC1400ディレクトリ配下のtruffe-config.jsの接続先を7545から8545に変更する必要があります。
truffle-config.jsの23行目の部分を変更してください。以下は変更後のファイルです。
truffle-config.js
require('dotenv').config();
require('babel-register');
require('babel-polyfill');
const HDWalletProvider = require('truffle-hdwallet-provider');
const providerWithMnemonic = (mnemonic, rpcEndpoint) => () =>
new HDWalletProvider(mnemonic, rpcEndpoint);
const infuraProvider = network => providerWithMnemonic(
process.env.MNEMONIC || '',
`https://${network}.infura.io/v3/${process.env.INFURA_API_KEY}`
);
const ropstenProvider = process.env.SOLIDITY_COVERAGE
? undefined
: infuraProvider('ropsten');
module.exports = {
networks: {
development: {
host: 'localhost',
port: 8545, //この部分を7545から8545に変更します。
network_id: '*', // eslint-disable-line camelcase
gasPrice: 0x01,
},
ropsten: {
provider: ropstenProvider,
network_id: 3, // eslint-disable-line camelcase
gasPrice: 5000000000,
},
coverage: {
host: 'localhost',
network_id: '*', // eslint-disable-line camelcase
port: 8555,
gas: 0xfffffffffff,
gasPrice: 0x01,
},
ganache: {
host: 'localhost',
port: 7545,
network_id: '*', // eslint-disable-line camelcase
},
dotEnvNetwork: {
provider: providerWithMnemonic(
process.env.MNEMONIC,
process.env.RPC_ENDPOINT
),
network_id: parseInt(process.env.NETWORK_ID) || '*', // eslint-disable-line camelcase
},
},
compilers: {
solc: {
version: '0.5.10',
settings: {
optimizer: {
enabled: true, // Default: false
runs: 0, // Default: 200
},
},
},
},
};
コントラクトの初期設定を確認
デプロイする予定のスマートコントラクトのコンストラクタに渡す引数を設定します。migrationsディレクトリ下にある3_erc1400.jsを開いてください。以下の部分を一部変更していきます。
3_erc1400.js
var ERC1400ERC20 = artifacts.require('./ERC1400ERC20.sol');
const CERTIFICATE_SIGNER = '0x29652B62CC3374F68f8d1e9d17eB76561E78512C';
const controller = '0x29652B62CC3374F68f8d1e9d17eB76561E78512C';
const partition1 = '0x5265736572766564000000000000000000000000000000000000000000000000'; // Reserved in hex
const partition2 = '0x4973737565640000000000000000000000000000000000000000000000000000'; // Issued in hex
const partition3 = '0x4c6f636b65640000000000000000000000000000000000000000000000000000'; // Locked in hex
const partitions = [partition1, partition2, partition3];
module.exports = function (deployer, network, accounts) {
deployer.deploy(ERC1400ERC20, 'ERC1400Token', 'DAU', 1, [controller], CERTIFICATE_SIGNER, partitions);
};
トークン名・トークンシンボルを設定
下記の[トークン名]、[トークンシンボル]を好みの英数字に変更して構いません。3_erc1400.jsファイルの12行目の部分になります。deployer.deploy(ERC1400ERC20, [トークン名], [トークンシンボル], [granuarity], [controller], CERTIFICATE_SIGNER, partitions);
権限をもつアカウントを設定
CERTIFICATE_SIGNERとcontrollerで、特別な権限をもつアカウントを設定することができます。今ganache-cli側がアカウントアドレスを用意してくれているので、genache-cliのターミナルから1番上のアドレスをコピーして、CERTIFICATE_SIGNERとcontrollerに入れておきます。
アドレスはAvailable Accounts以下の部分です。Private Keys以下は秘密鍵になるので間違わないようにしてください。以下のようにしてアカウントアドレスを正しく代入してください。
const CERTIFICATE_SIGNER = '0x29652B62CC3374F68f8d1e9d17eB76561E78512C';
const controller = '0x29652B62CC3374F68f8d1e9d17eB76561E78512C';
CERTIFICATE_SIGNERとは
CertificateControllerMock.solでは、以下のように説明されています。
Address used by off-chain controller service to sign certificate
STの発行や移転を実行するとき、オフチェーンの証明データ(バイトデータ)を持っていないとメソッドが実行できません。CERTIFICATE_SIGNERに設定されたアカウントは、証明に署名をする役割を所持し、証明データを持っていなくても、それらの制限のあるメソッドを実行することができます。
controllerとは
KYCを受けた投資家のアカウントアドレスが記載されているホワイトリストを管理します。投資家のアドレスを登録したり、取り消したりできます。これは主にAML/KYCプロバイダーの役割になります。
またControllerは、発行したセキュリティトークンにドキュメントを登録することができます。ブロックチェーン上に登録されることで、投資家はその証券が安全なものなのかどうか、改ざんされていないのかどうか(ハッシュを登録できることによって実現する)、また最新の情報を得るなどが可能になります。これは主にトラスト(信用)を提供するプロバイダー(監査法人など)の役割になります。
partitions(資産の種類)とは
9行目に記載されている配列partitionsには、資産の種類を表すバイト列を複数格納します。セキュリティトークンはpartitionごとに違う種類の資産を表し、違うpartitionのSTとは全く違うものとなります。つまりNFTであるということです。もちろん同じpartition同士は代替可能(NFTではない)です。
partitionsが実装されている理由は何でしょうか?例えばIT企業の株式を例にとります。まず普通株式といって、配当をもらったりや株主総会で議決権をもてる一般的な権利をもつ株式があります。また一方では、種類株式といって、株式を所有しても全く権利を持たない劣後株式や1株で20票分の投票権利をもてる優先株式といったものもあり、一企業が発行する株式にもいくつか種類(トランシェ)があります。
一企業がセキュリティトークンをイーサリアム上で発行するとき、複数の種類の株式に対応させる為に、複数のスマートコントラクトをデプロイするのでは、費用面やトークンの管理面などが煩わしです。なのでpartitionsという配列が用意されています。ここでは、3つの種類の株式を指定して発行できるようになっています。
コンパイル
それでは、起動しているganache-cliとは別タブで、ERC1400のスマートコントラクトをまずコンパイル(solidity言語で書かれたコードを機械語に翻訳します。)していきます。
$truffle compile
以下のようになれば、コンパイルが成功です。
ERC1400$truffle compile
Compiling ./contracts/CertificateController/CertificateController.sol...
Compiling ./contracts/ERC1400.sol...
Compiling ./contracts/IERC1400.sol...
Compiling ./contracts/Migrations.sol...
Compiling ./contracts/mocks/CertificateControllerMock.sol...
Compiling ./contracts/mocks/ERC1400Partition.sol...
Compiling ./contracts/mocks/ERC1400RawMock.sol...
Compiling ./contracts/mocks/ERC1400RawTokensRecipientMock.sol...
Compiling ./contracts/mocks/ERC1400TokensSenderMock.sol...
Compiling ./contracts/mocks/ERC1820ImplementerMock.sol...
Compiling ./contracts/token/ERC1400Partition/ERC1400Partition.sol...
Compiling ./contracts/token/ERC1400Partition/IERC1400Partition.sol...
Compiling ./contracts/token/ERC1400Raw/ERC1400Raw.sol...
Compiling ./contracts/token/ERC1400Raw/ERC1400RawIssuable.sol...
Compiling ./contracts/token/ERC1400Raw/IERC1400Raw.sol...
Compiling ./contracts/token/ERC1400Raw/IERC1400TokensRecipient.sol...
Compiling ./contracts/token/ERC1400Raw/IERC1400TokensSender.sol...
Compiling ./contracts/token/ERC20/ERC1400ERC20.sol...
Compiling ./contracts/token/ERC20/ERC1400RawERC20.sol...
Compiling erc1820/contracts/ERC1820Client.sol...
Compiling openzeppelin-solidity/contracts/access/Roles.sol...
Compiling openzeppelin-solidity/contracts/access/roles/MinterRole.sol...
Compiling openzeppelin-solidity/contracts/math/SafeMath.sol...
Compiling openzeppelin-solidity/contracts/ownership/Ownable.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/IERC20.sol...
Compiling openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol...
Writing artifacts to ./build/contracts
デプロイ
コンパイルに成功したら、次はいよいよプライベートネットにコンパイル済みのコントラクトをデプロイしていきます。
$truffle migrate
うまくいくと以下のようになります。
ERC1400$truffle migrate
⚠️ Important ⚠️
If you're using an HDWalletProvider, it must be Web3 1.0 enabled or your migration will hang.
Starting migrations...
======================
> Network name: 'development'
> Network id: 1568079902321
> Block gas limit: 6721975
1_initial_migration.js
======================
Account to load with ETH: 0xb508711F4C86EfB4A56337c4688ba671531Ecf76
Deploying 'Migrations'
----------------------
> transaction hash: 0x60879a5bbdf1e9f1a92d4a7649139d2134af4cb63a80231a231d55fe420bdad3
> Blocks: 0 Seconds: 0
> contract address: 0x06e54c30E2b5425320406257Eb9Bd19d1812D317
> account: 0xb508711F4C86EfB4A56337c4688ba671531Ecf76
> balance: 99.999999999999807353
> gas used: 192647
> gas price: 0.000000001 gwei
> value sent: 0 ETH
> total cost: 0.000000000000192647 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.000000000000192647 ETH
2_erc1820_registry.js
=====================
⠋ Saving migration to chain.
> ERC1820 deployment: Success --> 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24
> Saving migration to chain.
-------------------------------------
> Total cost: 0 ETH
3_erc1400.js
============
Deploying 'ERC1400ERC20'
------------------------
> transaction hash: 0xa5a74bfaf6f1566d4de761a1339a443794200716bdae39fe2756dac7fa08e933
> Blocks: 0 Seconds: 0
> contract address: 0x9909Fd3E2C90693AaCb3F82f34AB25115c21fa3D
> account: 0xb508711F4C86EfB4A56337c4688ba671531Ecf76
> balance: 99.899579999993568288
> gas used: 6169943
> gas price: 0.000000001 gwei
> value sent: 0 ETH
> total cost: 0.000000000006169943 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.000000000006169943 ETH
Summary
=======
> Total deployments: 2
> Final cost: 0.00000000000636259 ETH
これでERC1400を無事ブロックチェーンにデプロイできました。まとめ
本記事は、『ConsenSys社のERC1400実装を動かす』の前編でした。ERC1400を動かしていくための環境構築とコントラクトのデプロイまでを行いました。次回では、デプロイしたコントラクトの関数を利用して、セキュリティトークンの発行・移転・償還を実行します。またセキュリティトークンならではの機能を動かして、ERC1400の理解を深めていきます。
後編はこちら。