智能合約(英語:Smart Contract)是一種旨在以信息化方式傳播、驗證或執行合同的計算機協議。智能合約容許在沒有第三方的狀況下進行可信交易。這些交易可追蹤且不可逆轉。智能合約概念於1994年由Nick Szabo首次提出。
以上解釋來自於維基百科git
因爲缺乏可信的執行環境,智能合約並無被應用到實際產業中,自比特幣誕生後,人們認識到比特幣的底層技術區塊鏈天生能夠爲智能合約提供可信的執行環境,以太坊首先看到了區塊鏈和智能合約的契合,發佈了白皮書《以太坊:下一代智能合約和去中心化應用平臺》,並一直致力於將以太坊打形成最佳智能合約平臺,因此比特幣引領區塊鏈,以太坊復活智能合約。github
在區塊鏈上運行的程序,一般稱之爲"智能合約",因此一般咱們將區塊鏈程序稱之爲智能合約,在區塊鏈上,由事件驅動,以代碼形式存在,可執行的特殊交易合同,它是代碼與數據的集合,是以太坊的核心。編程
Solidity是以太坊智能合約的編程語言,語法接近於JavaScript,是一種面向對象的語言,用於智能合約的開發,並可以編程成以太坊虛擬機(EVM)字節碼部署到以太坊底層區塊鏈網絡上,文件擴展名以.sol結尾,通常用於:安全
等對信任,安全和持久性要求較高的應用場景。網絡
相似於JVM,EVM是以太坊虛擬機(Ethereum Virtual Machine),是以太坊智能合約的運行環境,每一個以太坊節點中都包含EVM,EVM是一個隔離的環境,在EVM內部運行的代碼與外部沒有關聯,EVM運行在以太坊節點上,咱們將智能合約部署到以太坊區塊鏈網絡後,合約就能夠在以太坊網絡環境中運行了。app
編譯編程語言
以太坊虛擬機上運行的是字節碼,須要咱們在部署以前對合約進行編譯轉成字節碼和ABI(二進制接口,是智能合約的接口說明)ide
部署函數
合約部署就是講編譯好的合約字節碼,經過外部帳號以發送交易的形勢部署到以太坊的區塊鏈網絡上,有實際礦工出塊以後,纔算真正部署成功。工具
運行
目前而言,尚未特別完善的Solidity開發工具,如今可選性並很少,用的最多的是Remix,你們暫且先用這個吧
文件夾
最左邊是文件夾管理,裏面列出了當前的工做區裏的文件,remix能夠支持從本地文件夾讀取文件。
工做區
正中間是工做區,工做區上半部是代碼編輯區,在這裏能夠寫solidity合約。
下半部是日誌區,在執行智能合約時,會顯示transaction相關的信息。在輸出日誌的時候還能夠查看Details和Debug信息。
功能區
最右邊的是功能區,裏面有編譯,運行,設置和分析以及調試器和支持。
在編譯器點擊Details能夠查看編譯細節,裏面有NAME,METADATA,BYTECODE,ABI 等一些相關信息。
在設置裏面能夠選擇咱們的編譯器版本,和一些IDE的使用設置。
功能區提供了三個運行環境
在下面的衆籌項目中,咱們採用的是JavaScript VM,在該環境中,Remix由5個以太坊帳戶組成,每一個帳戶存有100個以太幣用於合約的測試
在該衆籌項目中,包含了兩個角色,關係爲多對多。
爲了對代碼進行比較全面的解讀,直接將註釋寫到代碼中,再也不單獨取出代碼塊進行說明
// 聲明solidity版本爲0.4.24 pragma solidity ^0.4.24; // 建立合約CrowFunding contract CrowFunding { //定義衆籌贊助方結構體 struct Investor{ address addr; //贊助地址 uint count ; //贊助數量 } //定義衆籌發起方結構體 struct BySponsor{ address addr; //接收地址 uint goalCount; //衆籌金額 uint receiveCount; //已經衆籌到的金額 uint investorNum; //衆籌次數 mapping (uint =>Investor) investors; //用於保存多個衆籌贊助方信息 } uint bySponsorNum = 0 ; //定義衆籌發起方的ID號 mapping (uint=>BySponsor) bySponsors; //定義映射用於保存多個合做發起方信息 //定義函數,用於生成衆籌發起方對象 function newBySponsor() payable { // 將合約發起方ID號增長1 bySponsorNum++; /* 建立合約發起方對象 衆籌地址爲:當前Accout地址 衆籌金額爲:經過Value值設置 */ BySponsor memory bySponsor = BySponsor(msg.sender,msg.value,0,0); //將該衆籌對象保存至映射bySponsors中 bySponsors[bySponsorNum] = bySponsor; } /*定義函數,用於查看建立的衆籌金額 傳入參數: bySponsorId 衆籌發起方ID 返回值: goalCount 建立的衆籌金額 */ function getGoalCount(uint bySponsorId) constant returns (uint){ // 經過bySponsorId從映射bySponsors中取出對應的bySponsor對象 BySponsor memory bySponsor = bySponsors[bySponsorId]; //返回bySponsor對象的goalCount屬性值 return bySponsor.goalCount; } //定義函數,用於實現衆籌贊助方的贊助功能,傳入參數爲衆籌發起方ID號,並定義函數類型爲payable function sponsor(uint bySponsorId)payable { // 經過bySponsorId從映射bySponsors中取出對應的bySponsor對象 BySponsor storage bySponsor = bySponsors[bySponsorId]; //設置合約代碼可執行條件是贊助的金額必須>0 require(msg.value >0); // 將贊助金額加入到bySponsor對象的receiveCount屬性中 bySponsor.receiveCount += msg.value; //衆籌次數累加 bySponsor.investorNum++; //將本次衆籌贊助方信息保存至映射investors中 bySponsor.investors[bySponsor.investorNum] = Investor(msg.sender,msg.value); //實現轉帳,從當前地址(衆籌贊助方地址)轉入bySponsor(衆籌接收方地址),金額爲Value中定義的值 bySponsor.addr.transfer(msg.value); } //定義函數,用於獲取已經衆籌到的金額,傳入參數爲衆籌發起方ID號 function getReceiveCount(uint bySponsorId) constant returns (uint){ // 經過bySponsorId從映射bySponsors中取出對應的bySponsor對象 BySponsor memory bySponsor = bySponsors[bySponsorId]; //返回bySponsor對象的receiveCount屬性值 return bySponsor.receiveCount; } //定義函數,用於檢查是否衆籌金額是否達標,傳入參數爲衆籌發起方ID號 function checkComplete(uint bySponsorId) constant returns (bool){ // 經過bySponsorId從映射bySponsors中取出對應的bySponsor對象 BySponsor bySponsor = bySponsors[bySponsorId]; // 判斷設定的衆籌金額是否有效(不爲0),而且已經衆籌到的金額是否大於等於建立的衆籌金額 if (bySponsor.receiveCount >= bySponsor.goalCount && bySponsor.goalCount >0){ return true; }else { return false; } } }
智能合約運行步驟已在上文提到
調用方法
調用方法查看衆籌設定金額,已經衆籌到的金額,是否衆籌完成等信息,注意此時ID爲1
切換Account =>定義捐助金額 =>填寫捐助對象(ID爲1) =>執行sponsor
日誌信息
再次執行捐助100後,查看結果
至此,該衆籌案例代碼測試完畢
文中代碼已上傳至github中
https://github.com/DiaboFong/constractDemos/blob/master/demoCrowFunding.sol