Etherを賭けて当たったらEtherが貰えるルーレットアプリを作ってみました。
Ropsten上にアップしたので良かったら遊んでください。
テストネットなので賭博法的なものには引っかからないです!はずです!
遊び方
メタマスクを使う場合にはRopstenのアカウントを選んでください。
あとは好きなマスを選んでEtherを賭けてStartボタンを押すだけです。
トランザクションが処理されたらルーレットが回り始めます。
当ったら選んだマスに応じてEtherがゲットできます。(一般的なルーレットの返還率)
コントラクト
胴元
デプロイ時に3etherをコントラクトに渡しています。
掛け金の最大は0.03ehterで、仮に数字を当てたとしても36倍の返金(1ether強)なので、誰かがいきなり数字を3回連続で当てなければ大丈夫でしょう。
判定
ブロックのタイムスタンプを使って乱数を出力しています(0~37)。
0は0で00は37です。
あとは別に大した処理は入れていません。偶数に賭けて当たればベットの2倍を返したり、そんな処理です。
ブロックのタイムスタンプに関してはマイナーが操作できちゃうっぽいのであまり良い乱数の生成方法ではないと思いますが、お遊びなので今回はその方法を使いました。
Javascriptで乱数を生成してコントラクトに送る方法も考えたのですが、それも結局ユーザーが操作できてしまうので、コントラクト上で乱数生成してます。
テスト
シンプルなDAppなので、簡単に2種類のテストを作りました。
- デプロイときに1etherを渡したら、ちゃんとコントラクトが1etherを持っている。(コンストラクタが正常に動いている)
- ベットが当たれば賭けた場所に応じた返金があり、外したらコントラクトの所持するEtherが増える
フロントエンド
一度本を読んだ程度の知識しかなく、初めて実装したので正直ここに一番時間かかりました。
手順として、下記の手順で作りました。
ルーレット背景
-
context.arc()
を使って扇を書く。38要素あるので中心角は38/360度 - 上の扇を38個描画する
- 半径の小さい背景色白の扇を内側に同じように描画
ルーレット数字
基本的には0から順番に数字を入れました。基本的にはコンテキストの中心(ルーレットの中心)から右側に半径弱分移動してから数字を描画しました。ただ、各数字はその右側からずれているのでコンテキスト自体を回転させて各数字を描画しました。
- コンテキストの左上をコンテキストの中心に移動
- コンテキストを
rotate()
を使って回転 - コンテキストを元の位置に戻す
- コンテキストがルーレットの中心から回転しているので、この状態で右側半径弱分のところから数字を描画
- これを38要素分行う
コンテキストは左上からしか回転が行えないので、コンテキストの左上を中心にずらして回転させてから元に戻しました。
ルーレット回転
ルーレットの回転はこちらのサイトを参考に作りました。回転を行うメソッドにどこで止まるかの引数を与えて、指定のところに止まる様に作りました。
どこで止まるかの引数はコントラクトが実行された時点でブロックチェーンからブラウザが情報を受け取る様になっています。
- 最初にルーレットが15回転くらい止まる様に設定
- 止める数字に応じてもう少しだけ回す
- 少しずつ減速して最終的に目的のところで止まる
一周が38要素あるのに対して11要素ずつ回る設定(11要素分移動したルーレットを描画する)をしたので、例えば始点を0とすると、382 % 116 = 76 % 66 = 10になるので6回描画すると10に止まります。
こんな感じで各数字の時にどのくらいの回数再描画すれば目的のところに止まるかを配列にして、メソッドに渡すことで、止めたいところにルーレットが止まる様にしました。
今考えると簡単なのですが、かなり時間かかりました。。。
まとめ
できたこと(学んだこと)
- payableを使ってEtherを送るコントラクトの作成
- Canvas機能の基本的な使い方
やりたいこと(疑問点)
- 安全な乱数の生成(oraclizeとか)
- privateとかinternalのファンクションはテストできない?(今回はテストの時だけpublicにした)