さて、LEARNの第1回「ETH-dApp」のラストSection 4!
Lesson 1. 抽選機能を追加
抽選機能
uint256 private seed;
コントラクトのprivate変数にseed
を持たる
seed = (block.timestamp + block.difficulty) % 100;
コンストラクタ内で初期化。
wave
ファンクション内でseed
が50以下(100で割ってるから・・・51%かな)であれば送金しないというロジックに。
seed = (block.difficulty + block.timestamp + seed) % 100;
console.log("Random # generated: %d", seed);
if (seed <= 50) {
console.log("%s did not win.", msg.sender);
return;
}
seedの生成には、ハッカーからの攻撃を防ぐためにも、ランダム性を強化することで対処する。
そもそもコードはブロックチェーン上に公開されてしまうので、信頼できる乱数生成のアルゴリズムを作ることが重要。
3回目でやっと勝てたので、残高が変わったのがわかる
$ npx hardhat run scripts/run.js Compiled 1 Solidity file successfully Wave Portal ver 0.1.3 with lottery. Contract deployed to: xxxxx Contract balance: 0.1 We have 0 total waves! xxxxx waved w/ message The 1st messsage! Random # generated: 48 xxxxx did not win. Contract balance: 0.1 We have 1 total waves! xxxxx waved w/ message The 2nd message!! Random # generated: 27 xxxxx did not win. Contract balance: 0.1 We have 2 total waves! xxxxx waved w/ message The 3rd message!!! Random # generated: 83 xxxxx won. Contract balance: 0.0999 We have 3 total waves! [ [ 'xxxxx', 'The 1st messsage!', BigNumber { value: "1673445731" }, waver: 'xxxxx', msg: 'The 1st messsage!', timestamp: BigNumber { value: "1673445731" } ], [ 'xxxxx', 'The 2nd message!!', BigNumber { value: "1673445732" }, waver: 'xxxxx', msg: 'The 2nd message!!', timestamp: BigNumber { value: "1673445732" } ], [ 'xxxxx', 'The 3rd message!!!', BigNumber { value: "1673445733" }, waver: 'xxxxx', msg: 'The 3rd message!!!', timestamp: BigNumber { value: "1673445733" } ] ]
クールダウン機能を追加
mapping(address => uint256) public lastWavedAt;
mapping
を使って、ハッシュテーブルのような形で最終抽選日をアドレスごとに持たせる。
※本物のハッカーは、アドレス分散させて攻撃してきそうだけど、、、
require(
lastWavedAt[msg.sender] + 15 minutes < block.timestamp,
"Wait 15m"
);
wave
の一番最初にチェックを記載。
15分経ってない場合は、15分待てというエラー。
$ npx hardhat run scripts/run.js Wave Portal ver 0.1.3 with lottery. Contract deployed to: xxxxx Contract balance: 0.1 We have 0 total waves! xxxxx waved w/ message The 1st messsage! Random # generated: 88 xxxxx won. Contract balance: 0.0999 We have 1 total waves! xxxxx waved w/ message The 2nd message!! Random # generated: 87 xxxxx won. Contract balance: 0.0998 We have 2 total waves! xxxxx waved w/ message The 3rd message!!! Random # generated: 63 xxxxx won. Contract balance: 0.0997 We have 3 total waves! Error: VM Exception while processing transaction: reverted with reason string 'Wait 15m' at WavePortal.wave (contracts/WavePortal.sol:29) at processTicksAndRejections (node:internal/process/task_queues:96:5) at runNextTicks (node:internal/process/task_queues:65:3) at listOnTimeout (node:internal/timers:528:9) at processTimers (node:internal/timers:502:7) at HardhatNode._mineBlockWithPendingTxs (/home/ec2-user/environment/ETH-dApp/my-wave-portal/node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1815:23) at HardhatNode.mineBlock (/home/ec2-user/environment/ETH-dApp/my-wave-portal/node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:504:16) at EthModule._sendTransactionAndReturnHash (/home/ec2-user/environment/ETH-dApp/my-wave-portal/node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1522:18) [ [ 'xxxxx', 'The 1st messsage!', BigNumber { value: "1673445851" }, waver: 'xxxxx', msg: 'The 1st messsage!', timestamp: BigNumber { value: "1673445851" } ], [ 'xxxxx', 'The 2nd message!!', BigNumber { value: "1673445852" }, waver: 'xxxxx', msg: 'The 2nd message!!', timestamp: BigNumber { value: "1673445852" } ], [ 'xxxxx', 'The 3rd message!!!', BigNumber { value: "1673445853" }, waver: 'xxxxx', msg: 'The 3rd message!!!', timestamp: BigNumber { value: "1673445853" } ] ]
「Wait 15m」エラーが出ているのを確認。
ここは3回目のメッセージを送ったアドレスを使って再度wave
を呼び出し、try/catch
でエラーだけ出力してみた。
ということで、Lesson 1は終了。
Lesson 2. UI改善とサーバホスティング
UI改善
UI改善については、そこまで本気になる必要は無いので、自社サイトに寄せてこんな感じにして完了。
サーバホスティング
Vercelというサービスを使うと良いとのこと。
Vercel is the platform for frontend developers, providing the speed and reliability innovators need to create at the moment of inspiration.
Vercelはフロントエンド開発者のためのプラットフォームで、スピードと信頼性を提供することで、すぐに創れるようになると。
どんな機能かはわからないけど、、、一旦サインアップ完了。
で、まずは、ここで一旦GitHubに一通りプッシュします。
※当然、プライベートキーとかの重要な情報には注意して・・・
Dashboardから「Add New…」>「Project」を選択。
Git Repositoryを選択してDeploy。
あら・・・エラーだ。。。
色々検索した結果、そもそものNode.jsのバージョンが違っていた模様。
ProjectのSettings>GeneralのNode.js Versionを16.xにして再実行することでエラー解消。
まさか無料でドメインは変えられないよな、と思って試してみたら簡単にできるようで・・・
すごいなこのサービスは。
faviconとか変えてみたけど、og:imageとかはそのままだったので、こんな感じで出てしまったけど、ま、いいか。
ということで、最初のコンテンツは完了!!!
あ、これでNFTがもらえるかな????