//tips
おもろい。tiktokのアルゴリズム。
Tiktokを頑張って触っているがきつい。TOPページをなんとかニュースで埋めようとしているが。踊ってる人が出まくる。
//smart contract
前回の土日ではslitherを試し、エラー部分を改善した。
ツイートでsmart contractは将来的にデータベースの役割を担うとのコメントを見て衝撃を受けたが、分散化して、検証承認のプロセスを踏む分、即座に反応を返せないので、まだまだデータベースとしての活用は難しく、従来のデータベースとの併用で利用した方がよさそうという考え方に着地した。
Solidityについて下記をじっくり読んだ方がよさそうなので、今回はクリプトゾンビで準備体操をしたのちにこちらを読み込むことにする。クリプトゾンビは少し古いがアイデアは一緒。
https://docs.soliditylang.org/en/v0.8.15/
interfaceでは他のコントラクトにアクセスでしてgetできる情報を取得することができる。zombiefeeding.sol内にcontract KittyInterface {とcontract ZombieFeeding is ZombieFactory {を作ることになる。
contract NumberInterface {
function getNum(address _myAddress) public view returns (uint);
}
contract MyContract {
address NumberInterfaceAddress = 0xab38...;
// ここは、イーサリアム上のFavoriteNumberコントラクトのアドレスが入る。
NumberInterface numberContract = NumberInterface(NumberInterfaceAddress);
他のコントラクトの関数をそのまま流用できるのは素晴らしい。チェーン上のデプロイコントラクトは関数の束のように考えて、チェーン内で許可があれば相互に参照できる感じになるのか。
ここでは初期化ようにアドレスを使い、コントラクト初期化後に、実際にコントラクトを操作する.getNum(msg.sender);を読んでいる。最新バージョンでもこの仕様が継続されているようであれば、どういう考え方なのか確認しておく。ちなみに先日作成したオリジナルNFTのコードでは使用していない。
function getNum(address _myAddress) public view returns (uint);
function feedOnKitty(uint _zombieId, uint _kittyId) public {
uint kittyDna;
(,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
feedAndMultiply(_zombieId, kittyDna);
}
}
以前学んだようにスクリプトのabiをwebソケットの部品として組み込むことでインスタンス化でき、そのインスタンスを自身のアドレスを介して操作していくイメージ。
基本的にはデプロイ完了時点でabiはコントラクトと一緒にブロックチェーン上にあるはず。
デプロイしたコントラクトを利用するには、そのコントラクトのアドレスとabiをeth scanから引っ張ってくる必要がある。
var abi = /* abi generated by the compiler */
var ZombieFeedingContract = web3.eth.contract(abi)
var contractAddress = /* our contract address on Ethereum after deploying */
var ZombieFeeding = ZombieFeedingContract.at(contractAddress)
ブロックチェーンはnodeの集合体で、nodeを保有していない場合、infura nodeに間借りして、そこのapiを使用する。そのapiに連結させたメタマスクなどのMnemonic+providerをweb3部品と結合させることで、web3インスタンスが生成でき、コントラクトへのアクセスができると認識している。
コントラクトにデプロイした最初のコードは永久にブロックチェーン上に残ることになるのだが、もし外部依存したものが破壊されてしまったら、自身のコントラクトも放棄せざるを得なくなる。なので、外部依存しているものは内部で変更可能にしておくことが重要。つまり、関数化して値の更新を可能な状態にしておく。
KittyInterface kittyContract;
function setKittyContractAddress( address _address) external {
kittyContract = KittyInterface(_address);
}
また、コントラクト確認の際には、オーナーにどの程度特別な権限が与えられているかを事前に確認しておく。
アプリにする上で知っておかなければならないことは、Solidityでは、ユーザーが関数を使用するたびに、ガスを支払うこと。ガスを支払う以上のメリットがない限りは使われない。
逆にいうと、コストの観点から、イーサリアムは他のプログラミング言語よりもずっとコードの最適化がシビアに求められる。
関数を実行する時には、ネットワーク上で必要になるすべてのノードで同じ関数が実行されて、出力が正しいことを検証する。
ガスが課されるのは、ネットワークの計算資源を食い潰されないため。
struct内では、uintの使用領域を、圧縮できるため、できる限り小さな整数のタイプを扱うことで計算コストを削減できる。
now変数は、現在のunixタイムスタンプ、つまり1970年1月1日から経過した秒数を表示する。
関数の中にstorageを引数に加えることの意味は、引数に値を新たに渡すのではなく、関数にゾンビの参照そのものを渡すことで、無駄な受け渡しを省いている。参照なので安そう。参照であるため既に自分で定義されたものだということでinternalまたはprivateを使用。
function _doStuff(Zombie storage _zombie) internal {
publicやexternalの関数は必ず、誰かに悪用されることはないか、という視点で見直すこと。onlyOwnerのような修飾子をつけない限り、誰でも関数を実行し、好きなデータを渡すことが可能。
viewをつけることで、関数の実行にはローカルノードへの問い合わせるだけでよく、ブロックチェーン上にトランザクションを生成する必要がないことをweb3.jsに伝える。トランザクションを生成すると全てのノードで実行する必要があり、ガスが必要になる。ガスは各ノードでの検証が発生するトランザクション生成に対するコストであることがわかる。
コストを抑えるために、絶対に必要な場合を除いてデータをstorageに書き込まないようにする。
関数の中でmemoryキーワード付きで配列を生成すると、storageに書き込むことなく新しい配列を作ることができる。