---
# System prepended metadata

title: Beard | C0041103 - 第 4 週作業
tags: [Solidity 工程師實戰營第 4 期]

---


# Beard | C0041103 - 第 4 週作業


## 發行NFT 並有盲盒功能
- Contract Address:
https://goerli.etherscan.io/address/0x984926718f7a9956594349f442311adb661625bb
- gist:
https://gist.github.com/BeardYing/87bb554a828b49ef6aded48d016717db
- goerli.looksrare:
https://goerli.looksrare.org/collections/0x984926718f7A9956594349f442311Adb661625Bb

#### 作業需求
> 朋友想要請你發行 NFT，希望採用盲盒模式來增加神秘感，購買時並不知道裡面是什麼，等到一定的時間，盲盒就會開啟，才會知道買的 NFT 是什麼樣子

> - 引用 ERC721 標準，可 mint 你的 NFT
> - 需提供 Looksare Testnet Goerli NFT項目網址
> - 宣告控制盲盒開關的參數 revealed
> - 寫一個 switchRevealed function 可以控制盲盒開啟與否
> - 開關控制會讓 tokenURI 的值有所不同
> - 若 revealed 是 true，tokenURI 設定解盲後的 json
> - 若 revealed 是 false，tokenURI 設定尚未開盲盒的 json

#### 說明
- 由於製作的功能有白名單/公售功能，所以部署合約後，直接切換成 public sale
- 比較特別在於，這專案撰寫時，把setBaseURI 跟 解盲寫在一起，為了避免解忙時手忙腳亂，也可避免太早上傳正式圖片洩漏。
    - 設定盲盒圖： <code>*setBaseURI（ipfs://[盲盒圖片的 json CID], false）*</code>
    - 解盲： <code>*setBaseURI（ipfs://[圖片的json資料夾 CID]/, true）*</code>
- 其餘說明有另外整理於：[KTOne NFT發行筆記](https://hackmd.io/hjrNHSj-T3uZAd3pK7xVgg)
- 盲盒截圖
![](https://i.imgur.com/uKzOzay.png)
- 解盲截圖
![](https://i.imgur.com/vOvNJpE.png)


## 用 chainlink VRF 產生隨機數來實作樂透
- Contract Address: 
https://goerli.etherscan.io/address/0x6a897f2616729dc28fb7bd1e834ec663a0526484
- gist: 
https://gist.github.com/BeardYing/3fd86441ccabf674e2e68d7abed60b57
- 基本題：Y 
- 進階題：Y
- (有些許改版，不過應該是有達到基本/進階版想要的功能效果)
#### 作業需求
> ##### 基本題
> - 多人可以參與這期投注，該期投注的總金額會作為當期樂透發放獎金
> - 實作一個參與樂透 enter Function，參與者必須投入 0.001 ether 才能參與這期樂透（提示：可定義 enter function，並用 payable 接收 eth）
> - 可以知道參與這期樂透有多少人
> - 可以知道這期總獎金額目前是多少 ether
> - 合約需定義 getRandomNumber Function，必須使用 ChainLink VRF 預言機來取得隨機數
> - 部署合約者是 owner
> - 開獎條件：本期樂透總獎金必須累積到某個金額（例：0.01 eth），owner才可開獎。
> - 幸運得主可獲得樂透本期總投注獎金 100%
> ##### 進階題
> - 設定每一期樂透開獎時間限制（例如10分鐘）開獎一次
  若開獎時間未到，owner 無法進行開獎
  若已超過開獎時間，未累積到指定開獎金額（例：0.01 eth），則退款給本期所有投注者
  

#### 作業說明
- 本次作業稍加調整成貼近樂透的投注方式，並且盡可能實作原本題目的需求。

#### 遊戲方式與規則
1. 一次只有一個樂透遊戲啟用，可投注號碼 1 ~ 5 (初始化時可設定)
2. 若未達到最低標準，進行退費
3. 沒中獎，獎金累積到下一期，直到中獎為止
4. 當期中獎者根據 當期中獎+累積獎金 依照投注比例平分給中獎人員


#### 程式說明/操作
1. 取得目前投注總金額： <code>*lotterys[lotterRound].pot* </code>
2. 下注： <code>*entry(uint256 _no, uint256 _betCount)*</code>
    - *uint256 _no* : 投注號碼
    - *uint256 _betCount* : 想投注的數量（與中獎分潤有關）
3. 合約所屬者可以使用：
    - <code>*getWinnerProcess()*</code>
        - 若是投注不足，會直接退款
        - 若是投注超過限額，開始對預言發出中獎隨機碼請求。
    - <code>*startNewLottery()*</code>
        - 若是本期的投注金額為 0，而且投注時間已過期，則 Owner 可以新建樂透。
        - 若是還有在進行中或是尚未開獎的樂透遊戲，無法新建樂透
    - <code>*reward()*</code>
        - 若沒人中獎將獎金放入 potPool，等待下次人員中獎時，取出平分。
        - 若有人中獎，依據投注金額比例分配獎金
4. 處理順序：<code>*getWinnerProcess()*</code> ---[等待預言機回傳]--> <code>*reward()*</code> ---> <code>*startNewLottery()*</code>


#### 試玩看看

- 第一期投注 1號 3號各一注，結果開獎為2號，沒中獎，獎金0.002納入 potpool
    ![](https://i.imgur.com/dFHkL6w.png)
- 第二期沒人下注，直接開立新局第三期
- 第三期：兩人包牌
    -  (0x00c5) 1~5各買1注 
    -  (0xadf8) 1~5各買2注
    - 總獎金來到：0.002 + 0.005 + 0.010 = 0.017 eth
        ![](https://i.imgur.com/GH1swur.png)<small><i> - 由於沒截圖到，直接利用最後一筆投注(block=	7484811)查看目前合約變化</i></small>
- 中獎號碼為3號，獎金分別投注者為
    - 0x00c5 1注 / 0xadf8 2注 ，可利用 function 查詢
     ![](https://i.imgur.com/OEs3ZUP.png)
    - 計算分配獎金 
        - 0x00c5 可獲得 (0.017 / 3) * 1 = 0.00566666667 ether
        - 0xadf8 可獲得 (0.017 / 3) * 2 = 0.01133333333 ether
        - 在txn紀錄中，可以看見的變換狀態：[Txn Status](https://goerli.etherscan.io/tx/0xfd840d7ce70b9cf33d7afbc776aa24ef488f83391b2c5d04ba6de371bce39064#statechange)
        
        ![](https://i.imgur.com/GMoK0mf.png)

    - 建立第四期樂透，並且測試投注額度不足退款，可看到 Start New 後僅有一筆 0.001 eth 的 Entry 請求，故未達到最低門檻：0.002 eth
      ![](https://i.imgur.com/OyDvMGw.png)
    
    - 在Get Winner Process時，判斷未達最低門檻，進行退款
      ![](https://i.imgur.com/FPBdgdq.png)

###### tags: `Solidity 工程師實戰營第 4 期`