Ethereumめも

スマートコントラクト / Ethereum

Ethereumは仮想通貨の一種。単位はEther。現在のレートは1Ether = 7万円くらい。 他の仮想通貨と同様に、コンピューター同士が通信することで運営されており、取引履歴は全世界で共有される。

Ethereumネットワークにプログラム(スマートコントラクトという)をアップロードして動かすことができる。いつどのアカウントがどのプログラムを呼び出したかが、取引履歴と同様に共有される。

スマートコントラクトの内容は一度アップロードしたら変更することができない。

ユーザーの入力をスマートコントラクトが処理して内部状態を変更する仕組みになっている。

Ethereumにアップロードされたスマートコントラクトはそれ自体が"自動化されたアカウント"として働く。スマートコントラクトは内部状態の一種としてEtherを保持することができ、スマートコントラクトを構成するオペコードの中には他のアカウントに送金したり、スマートコントラクトに情報を入力したりするものがある。

全てのアカウントはいつでもスマートコントラクトに対して情報を入力することができる。スマートコントラクトは入力された情報を処理する。エラーを吐くこともでき、その場合は全状態変更がなかったことになるが、履歴自体は残る。

Solidity

スマートコントラクト自体は独自の機械語で記述されている。 SolidityはJavascript風の構文をもつ言語で、スマートコントラクトにコンパイルすることができる。

グローバル変数

  • now 現在ブロックのタイムスタンプを取得する。現在時刻ではない。(ブロックチェーン上で実行しているので当たり前といえば当たり前)

  • msg.sender 現在実行中の関数を呼び出したアドレス。Ethereumでは、コントラクトがコントラクトを呼び出すことができるが、その場合は呼び出したコントラクトのアドレスになる。(ex. ユーザー → コントラクトA → コントラクトB、の順に呼び出された時、コントラクトB内でのmsg.senderはAのアドレスになる。)

  • tx.origin 上記のmsg.senderとは違い、関数コールの連鎖を引き起こした元のアドレス、つまりユーザのアドレスを取得する。コントラクトアドレスはtx.originにはなれない。

tx.originはマイナーが偽装できてしまうため、通常、アドレスを取得したい場合はmsg.senderを使うらしい。 また、アドレス取得にmsg.senderを使っておけば、コントラクトアドレスが関数を自動で呼ぶことができるので、そういう意味でもmsg.senderを使った方が良い。Multisig対応にもなるし。(なんとEthereumではマルチシグはスマートコントラクトを用いて構成されている)

コントラクトの移行

アップデートのたびに別のコントラクトを作り、そのたびにアプリケーション内のコントラクトアドレスを変更する、という形で良い。

ただ、それだけだと問題が発生する。コントラクトは移行できたから良いものの、肝心のデータが移行できない。新しくコントラクトを作り直すと、内部のデータは全て一度リセットされるからだ。

これを回避するために、データベース用のコントラクトを別に作り、その書き込み権限をコントラクトがアップデートされるたびに、最新のコントラクトに設定する、という方法があるらしいが、バグなどが怖いのでおすすめできない。

スマートコントラクトはその名の通り、その場限りの"契約書"的な使い方がじつは望ましい。e.g. カジノ
そうで無い使い方をする場合は、極力OpenZepperinなどのライブラリや既製のコードを使う必要がある。