手把手教你如何使用Chainlink鬧鐘在鏈上發起投票

買賣虛擬貨幣
以太坊上許多智慧合約都需要透過外部計時器觸發鏈上執行,因此dApp在鏈上發起投票時就會遇到問題,因為投票通常都有一個時間視窗。由於Solidity中沒有計時器,因此智慧合約的投票機制需要接入外部工具來啟動或關閉投票視窗。其實在傳統系統中,計時功能並不難實現,系統可以設定NTP時間與作業系統時間同步,也可以用實物鐘錶或計時器計時,甚至還可以用sleep表示式在一段時間內暫停程式碼執行。Solidity智慧合約中的事件由鏈下交易觸發,也就是說以太坊等區塊鏈需要接入鏈下鬧鐘觸發事件或呼叫函式。而好訊息是,開發者可以將Chainlink節點作為鬧鐘,可靠地觸發智慧合約執行。
本文將教大家如何在dApp中輕鬆實現投票時間控制。現在隨著越來越多dApp開始走DAO路線,將更多權力交到使用者手中,這種投票機制也變得愈發重要。具體步驟如下:· 將Chainlink功能包匯入智慧合約並繼承· 格式化並提交Chainlink sleep(“until”)請求· 將合約所有者設定成唯一有許可權發起投票的人
· 使用簡單的KYC確認每個地址只投一次票· 使用Getters函式檢視投票狀態本示例中使用的程式碼可以在GitHub中檢視,你還可以檢視方便部署的Remix。當然,這只是一個最基本的示例,你可以使用Chainlink“until”請求在任何時間點觸發任何事件。這個示例只是一個初始框架,你可以在上面開發其他需要時間控制功能的智慧合約。合約定義和建構函式:import "github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/ChainlinkClient.sol";
contract ChainlinkTimedVote is ChainlinkClient{  uint private oraclePayment;  address private oracle;  bytes32 private jobId;  uint private yesCount;
  uint private noCount;  bool private votingLive;  mapping(address => bool) public voters;  //only the contract owner should be able to start voting  address payable owner;  modifier onlyOwner {
  require(msg.sender == owner);  _;}   constructor() public {       setPublicChainlinkToken();       owner = msg.sender;
       oraclePayment = 0.1 * 10 ** 18; // 0.1 LINK       //Kovan alarm oracle       oracle = 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e;       jobId = "a7ab70d561d34eb49e9b1612fd2e044b";       //initialize votes       yesCount = 0;
       noCount = 0;       votingLive = false;}匯入ChainlinkClient並使用“is”關鍵詞繼承,就可以輕鬆向Chainlink節點請求資料。然後,我們需要定義幾個全域性變數,其中包括計時器預言機的地址,地址可以在Chainlinks (測試網)頁面上檢視。另外,我們還需要一個job spec ID和一些追蹤投票的變數,並且將投票者地址mapping為一個布林值,以確認地址是否投過票。最後,我們要定義一個修改器,規定只有合約所有者才有許可權傳送訊息呼叫函式。然後在建構函式中將合約所有者地址以及其他變數一同初始化。注:mapping不需要初始化,布林型別預設值是false。向Chainlink傳送請求,啟動投票:
function startVote(uint voteMinutes) public onlyOwner {         Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);         req.addUint("until", now + voteMinutes * 1 minutes);         //Start voting window then submit request to sleep for $voteMinutes         votingLive = true;         sendChainlinkRequestTo(oracle, req, oraclePayment);
}  //Callback for startVote request  function fulfill(bytes32 _requestId) public recordChainlinkFulfillment(_requestId) {         //$voteMinutes minutes have elapsed, stop voting         votingLive = false;}
我們合約的第一個函式startVote就需要向Chainlink發起請求。在這裡我們用到了onlyOwner修改器,確保只有合約所有者才有許可權發起投票。我們在《怎樣將智慧合約和API連線在一起》一文中提到,ChainlinkClient合約匯出一個Chainlink.Request的資料結構,這個資料結構可以根據具體需求變成不同的格式。示例中,我們在資料結構中新增的不是“get”請求,而是“until”。我們在建構函式中定義的Chainlink節點地址可以識別這個until字串,節點收到請求後會在規定時間內暫停任務流水線(task pipeline)(注:規定時間指“voteMinutes”分鐘時間)。在提交請求前,我們需要將votingLive設定成true,即成功開啟投票,投票函式會檢視變數狀態以允許或拒絕投票。然後我們就可以提交請求了,這時Chainlink節點會暫停任務流水線。這樣,我們就能在until請求設定的時間結束後呼叫fulfill回撥函式。當呼叫fulfill函式時,設定的投票時間已經結束,因此就可以將votingLive設定回false,將投票關閉。綜上所述,我們要先建立一個“until”請求,請求中包含規定時間,並將其傳送至某一節點,節點在規定時間內暫停後再呼叫fulfill函式。Chainlink計時器/鬧鐘實現起來就是這麼簡單!我們使用簡單的votingLive布林邏輯,就可以在向Chainlink鬧鐘提交請求之前啟動投票,並在暫停了一段時間後回撥函式被呼叫時關閉投票。在這個例子中我們僅僅使用了一個布林識別符號,但是你可以在其基礎上開發出其他的延時功能。進行投票並檢視投票狀態://Increments appropriate vote counter if voting is live
  function vote(bool voteCast) public {     require(!voters[msg.sender], "Already voted!");     //if voting is live and address hasn't voted yet, count vote       if(voteCast) {yesCount++;}       if(!voteCast) {noCount++;}       //address has voted, mark them as such
       voters[msg.sender] = true;}//Outputs current vote countsfunction getVotes() public view returns (uint yesVotes, uint noVotes) {return(yesCount, noCount);}
//Lets user know if their vote has been countedfunction haveYouVoted() public view returns (bool) {      return voters[msg.sender];}這裡就需要用到真正能實現投票的邏輯了。投票函式接受一個true/false的引數來檢驗使用者是否已經投過票,如果驗證透過,則計算投票,並將他們mapping中地址對應的值更新為true,表示他們已經投過票了。我們使用require表示式而不是if表示式來驗證地址。這樣一來,已經投過票的交易就會被拒絕。最後,由於以太坊交易不會返回結果,我們新增了一些簡單的view函式來檢視目前投票數量,並確認投票是否被統計。希望本文能夠讓大家瞭解Chainlink在主網上的其中一個實用功能,併為你們的智慧合約實現更大的價值。如果你想要了解Chainlink的其他功能,請關注Chainlink釋出的可驗證隨機數生成工具Chainlink VRF、接入Chainlink喂價機制開發流動性挖礦dApp或瞭解Chainlink預言機的最新研究成果公允排序服務。

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;