Ethereum上のSmart Contractで必要最低限な機能を持つTokenを実装し、
privatenetに登録してメソッドを呼び出すところまでやってみたので、その内容を共有したいと思います。
Contractの実装
まずは、本家のtoken解説記事を見ながら進めます。
最小構成は以下のコードのようです。
こちらをもとに機能をたしていこうと思います。
MINIMUM VIABLE TOKEN
The token contract is quite complex. But in essence a very basic token boils down to this:
contract MyToken {
/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
/* Initializes contract with initial supply tokens to the creator of the contract */
function MyToken(
uint256 initialSupply
) {
balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens
}
/* Send coins */
function transfer(address _to, uint256 _value) {
if (balanceOf[msg.sender] < _value) throw; // Check if the sender has enough
if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
balanceOf[msg.sender] -= _value; // Subtract from the sender
balanceOf[_to] += _value; // Add the same to the recipient
}
}
solidityのversionについて
ソースコードの冒頭に以下のような記述をするみたいです。
こちらの記事@Qiitaにもあるように
Solidity versionが0.4.9だと一部記述が変更されているので注意。
だそうです。
pragma solidity ^0.4.8;
インストールされたversionの確認
$ solc --version
solc, the solidity compiler commandline interface
Version: 0.4.11+commit.68ef5810.Linux.g++
-> いったん^0.4.11
で記述してみる。
最小限のものをデプロイ
gethプロセスおよびremixのサーバープロセスを立ち上げておきます。
(私はここでは、docker使って立ち上げています。)
結局以下のように実装しました。
pragma solidity ^0.4.11;
contract TestKumanoToken {
/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
/* Initializes contract with initial supply tokens to the creator of the contract */
function TestKumanoToken(
uint256 initialSupply
) {
balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens
}
/* Send coins */
function transfer(address _to, uint256 _value) {
if (balanceOf[msg.sender] < _value) throw; // Check if the sender has enough
if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
balanceOf[msg.sender] -= _value; // Subtract from the sender
balanceOf[_to] += _value; // Add the same to the recipient
}
}
- remixのContractタブにて
initialSupply
に適当に10000
をいれて「Create」ボタンを押下します。
callback contain no result Error: authentication needed: password or unlock
というエラーがでる。。。
Web3 deployの箇所で from が web3.eth.accounts[0] となっている。。。
つまり gethのメインアカウントをunlockしておかにとダメなようだ。。。
Web3 deploy
var initialSupply = /* var of type uint256 here */ ;
var test_kumano_token_sol_testkumanotokenContract = web3.eth.contract([{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"initialSupply","type":"uint256"}],"payable":false,"type":"constructor"}]);
var test_kumano_token_sol_testkumanotoken = test_kumano_token_sol_testkumanotokenContract.new(
initialSupply,
{
from: web3.eth.accounts[0], // <- ここ!
data: '省略',
gas: '4700000'
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
}
})
geth consoleにて
account[0]をunlockします。
> personal.unlockAccount(eth.accounts[0])
Unlock account 0xaa41331cdaac5b64189c9369f65baf6964387ec9
Passphrase: hit accounts[0] password & hit enter.
true
retry
再度「Create」ボタンを押してみます。
callback contain no result Error: insufficient funds for gas * price + value
ぐぐぐ・・・
なるほど・・でも確かにaccounts[0]の所持金が0ethなので、ただでContractは公開できませんよね。。。
geth consoleにて
採掘を行います。
※ genesis.jsonのdifficultyを低めに設定しておき、miningしやすくしておきます。
> miner.start()
true
ほどよいころあい(2分後くらい?)で、採掘を終了しておきます。
> miner.stop()
true
45 etherくらいたまったところで(mainネットで45eth欲しい^^)
re: retry
再度×2「Create」ボタンを押して見ます。
callback contain no result Error: invalid sender
ぐぐぐぐぐぐぐ・・・
genesis.jsonのconfigを修正
どうも立ち上げているgeth
の起動オプションとgenesis.json
のconfig.chainId
が一致していないためにおきている模様
go ethereum - Invalid sender error on private chain - Ethereum Stack Exchange
genesis.json
"config": {
"chainId": 15, // <- ここをnetworkidに合わせて、geth initし直し
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
re: re: retry
Waiting for transaction to be mined...
成功しました。
transactionを送信したので、miningを再開させて、とりこんでいきます。
> miner.start()
true
// eth.blockNumberみながらblockがすすんだらminer.stop()する
-> 0xa066c8e327d706af04966f78e5bec3403851a124
のアドレスにデプロイされました。
Contractを実行
geth consoleにて
> var test_kumano_token_sol_testkumanotokenContract = eth.contract([{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"initialSupply","type":"uint256"}],"payable":false,"type":"constructor"}]).at('0xa066c8e327d706af04966f78e5bec3403851a124')
> test_kumano_token_sol_testkumanotokenContract.balanceOf(eth.accounts[0])
10000
途中で少し予期しないエラーに阻まれましたが・・・
無事Tokenの最小構成であるTestKumanoToken Contract
を privatenetに登録し、ownerのtoken保有数を確認することができました。
以上になります。