//tips
//smart contract
Web3接続内容を細かく見ていく。
inbox=await new web3.eth.Contract(JSON.parse(interface))
これはweb3のethモジュールのcontractプロパティにアクセス。これは既存のブリックチェーンコントラクトとのコミュニケーションや新規コントラクトの生成を行うもの。引数には、ABIから、json化されたものをjsオブジェクトに戻して取得している。
つまり、ここではコントラクトの中身というよりは、コミュニケーションの土台となるインターフェースを規定する部分となる。
.deploy({data:bytecode,arguments:['Hi,there!']})
Deployでは新しいコントラクトを作成し、引数にはtransactionオブジェクトを取る。このdataはコントラクトのbytedataとなる。次のargumentsはコントラクト生成時に必要とする引数で、先のconstructor部分にあたる。
function Inbox(string initialMessage)public{
message= initialMessage;
}
initialMessage部分が引数に該当する。
.send({from:accounts[0],gas:'1000000'});
最後にコントラクトの内容をdeployする箇所となる。先のdeployはどちらかというとコントラクト生成部分にあたり、最後のsendメソッドの方が実際のdeploy作業を担っている。
From部分はコントラクトの創造主を取り、gasはtransaction時の許容負手数料の単位を表す。
先に述べたようにすでにブロックチェーンにあるコントラクトとコミュニケートする場合にはbytecodeは必要なく、ブロックチェーン上のコントラクトアドレスが代わりに必要となる。
また、awaitをつけることで、await以下のメソッドの値が返されるまで処理を一時停止する演算子のことができる。
Deployしたコントラクト内容の確認を行うため、describeの下にitでデプロイ時点、メソッド動作の確認を行う。
describe('Inbox',()=>{
it('deploys a contract',()=>{
console.log(inbox);
});
it('has a default message',async()=>{
//deploy後のコントラクトメソッドの確認
const message = await inbox.methods.message().call();
//inboxインスタンスの中のmethodの中からmessage()メソッドを呼ぶ
//message()はpublic string message
//.callはどのように呼ぶか。コストのかからない参照だけでなくtransactionも可能
assert.equal(message,'Hi,there!');
});
it('can change the message',async()=>{
await inbox.methods.setMessage('bye').send({from:accounts[0]});
const message = await inbox.methods.message().call();
assert.equal(message,'bye');
});
});
ここからはrinkebyネットワークに載っているinfuraも活用してdeployを進めていく。
Ganacheの場合はproviderから渡されて、web3に組み込まれる情報にアカウント情報がすでに含まれていたが、infuraを使用してネットワーク接続する場合は少し異なる。
Infura nodeから取得できるapiをproviderに渡す際に自身のメタマスクのニューモニックワードも一緒に渡すことでアカウントが認識される。
ターミナルからinfuraとの接続をサポートするツールをインストール。
npm install @truffle/hdwallet-provider
ここからはweb3、infura.api、ニューモニックワードを利用して、deploy操作を行う。
// deploy code will go here
const HDWalletProvider=require('@truffle/hdwallet-provider');
const Web3=require('web3');
const {interface,bytecode}= require('./compile');
//どのアカウントを使ってdeployするのか、どのネットワークのapi/nodeを使うのか
const provider=new HDWalletProvider(
//unlcok wallet provider
//アカウントのニューモニック/demoようのものを使用
'abc efg ...',
//infuraのパス
'https://rinkeby.infura.io/v3/c575a6e5d49d40df84996f7ddd432801'
);
//このweb3でネットワークのものとコミュニケーションできる
const web3 = new Web3(provider);
const deploy= async()=>{
const accounts =await web3.eth.getAccounts();
console.log('Attempting to deploy from account',accounts[0]);
const result=await new web3.eth.Contract(JSON.parse(interface))
.deploy({data:bytecode,arguments:['Hi there']})
.send({gas:'1000000',from:ccounts[0]});
//deploy先のアドレスをrecord
console.log('Contract deploy to',result.options.address);
provider.engine.stop();
};
deploy();
これでinfura nodeとweb3でのdeploy設定ができたのでnode deploy.jsでプログラムを実行することができる。
また、remixのinjected Web3環境を使用することで先にdeployしたアカウント宛にremixからコントラクトの更新をかけることができる。例えば、hi thereからbyeへの変更など。もちろんその分コストはかかる。
ベースの流れはわかってきたのでSolc v0.8.9までバージョンアップさせてみる。
mkdir inbox-updated
npm init
npm install solc web3 mocha ganache-cli @truffle/hdwallet-provider
さらにフォルダを移行。.solも更新。
pragma solidity ^0.8.9;//
contract Inbox{
string public message;
constructor(string memory initialMessage) {
message = initialMessage;
}
function setMessage(string memory newMessage) public {
message = newMessage;
}
}
ここでやっとmemoryとconstructorが登場した。
今度はlottery contracctを作成していくことにする。lottery contracctにprize poolを作成し、各送金主をplayers poolに入れておく。Managerが任意にpoolから1名選出する。選出されたらコントラクトからその人に対してprize pool の全額を送金し、このループを繰り返すものとする。
Managerがcontractのcreatorであり唯一プールに資金を移動させることができる。
enterメソッドではプレイヤーのアドレスアカウントからlotteryへの参加金額を確認し、pickWinnerメソッドはランダムに一人勝者を選び、prize poolの金額を送る。
これはremixで草案を作成していく。