智能合约(英语: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