Vyperでスマートコントラクト開発をしてみましょう。
本記事はそのための環境構築をする方法について説明しています。
Install Python3.6
Vyperを使うには、Python3.6以上が必要。
pyenvを使ってPythonをインストールする。
Install pyenv
$ brew install pyenv
.zshrcにPATHを追加
export PATH="$HOME/.pyenv/shims:$PATH"
Python3.6.xをインストール
$ pyenv install 3.6.7
Python3.6.xを指定
$ pyenv global 3.6.7
確認
$ python -V
# => Python 3.6.7
Install libralies
必要なライブラリをインストールしておく
$ brew install gmp leveldb
Install virtualenv
Pythonの仮想環境を使うことを公式ドキュメントは推奨しているので、virtualenvをインストールしておく。
virtualenvを使えばプロジェクトごとにPythonのバージョンやパッケージを管理できるので、他の環境を汚さずに済む。
It is strongly recommended to install Vyper in a virtual Python environment, so that new packages installed and dependencies built are strictly contained in your Vyper project and will not alter or affect your other development environment set-up.
https://vyper.readthedocs.io/en/latest/installing-vyper.html
virtualenvをインストール
$ [sudo] pip install virtualenv
確認
$ virtualenv --version
# => 16.1.0
Vyper用の仮想環境を構築する
仮想環境を作成
$ virtualenv -p python3.6 --no-site-packages vyper-test
作成した仮想環境をactivate
$ source vyper-test/bin/activate
Vyperをクローンする
$ git clone https://github.com/ethereum/vyper.git
$ cd vyper
$ make
$ make test #実行完了まで結構時間がかかる...
これで環境構築とプロジェクトのセットアップは完了。
正しくセットアップができたかどうかは、Cloneしたディレクトリで以下を実行して確認。
$ vyper examples/crowdfund.vy
Vyperについて
- Vyperの構文はPython3と同じ(ただし、Python3の全ての構文が使えるというわけではない)
- VyperはFileで構成されている
- Fileはオブジェクト指向言語におけるClassのようなもの
- 各FileはState Variables, Functions, structure-structs-typesで構成される
Functions
- コードを実行する1つの塊(他のプログラミング言語と同様に考えればOK)
- 必ず
@public
か@private
を指定する
Default function
-
__defalult__
で宣言する - functionの実行時に該当のものが見つからない時などに実行される
- Solidityのfallback functionのようなもの
- 必ず
@public
内で宣言する - 引数や返り値は持たすことができない
-
@payable
と組み合わせた場合、Etherを送った時には必ず実行される。これは送信したEtherとユーザーアドレスの間で差分が発生しないようにするため。 - グローバル変数
msg
からは以下の3つが取得できる-
msg.sender
: 送り手のaddress -
msg.value
:送信されたETHの量 -
msg.gas
: 提供されたgas代
-
Sample Function
Vyper公式ドキュメントにあるFunctionのサンプルコード。
- bidされたETHが最高入札額より大きかったら、入札に成功し、元の最高入札者にETHが返されるコントラクト
# Open Auction
# Auction params
# Beneficiary receives money from the highest bidder
beneficiary: public(address)
auctionStart: public(timestamp)
auctionEnd: public(timestamp)
# Current state of auction
highestBidder: public(address)
highestBid: public(wei_value)
# Set to true at the end, disallows any change
ended: public(bool)
# Create a simple auction with `_bidding_time`
# seconds bidding time on behalf of the
# beneficiary address `_beneficiary`.
@public
def __init__(_beneficiary: address, _bidding_time: timedelta):
self.beneficiary = _beneficiary
self.auctionStart = block.timestamp
self.auctionEnd = self.auctionStart + _bidding_time
# Bid on the auction with the value sent
# together with this transaction.
# The value will only be refunded if the
# auction is not won.
@public
@payable
def bid():
# Check if bidding period is over.
assert block.timestamp < self.auctionEnd
# Check if bid is high enough
assert msg.value > self.highestBid
if not self.highestBid == 0:
# Sends money back to the previous highest bidder
send(self.highestBidder, self.highestBid)
self.highestBidder = msg.sender
self.highestBid = msg.value
# End the auction and send the highest bid
# to the beneficiary.
@public
def endAuction():
# It is a good guideline to structure functions that interact
# with other contracts (i.e. they call functions or send Ether)
# into three phases:
# 1. checking conditions
# 2. performing actions (potentially changing conditions)
# 3. interacting with other contracts
# If these phases are mixed up, the other contract could call
# back into the current contract and modify the state or cause
# effects (Ether payout) to be performed multiple times.
# If functions called internally include interaction with external
# contracts, they also have to be considered interaction with
# external contracts.
# 1. Conditions
# Check if auction endtime has been reached
assert block.timestamp >= self.auctionEnd
# Check if this function has already been called
assert not self.ended
# 2. Effects
self.ended = True
# 3. Interaction
send(self.beneficiary, self.highestBid)
Others
Viperはコードの上から イベントの定義 -> 変数の型定義 -> メソッドの記述という順番を守らないとコンパイル時にエラーになります
https://blockchain.gunosy.io/entry/compare-solidity-viper
まだまだ情報が少なく、Vyper自体もアルファ版ですが、今後に期待です。