solidity的语言是为了能在以太坊上面部署智能合约
Solidity是一种语法类似JavaScript的高级语言。它被设计成以编译的方式生成以太坊虚拟机代码。在后续内容中你将会发现,使用它很容易创建用于投票、众筹、封闭拍卖、多重签名钱包等等的合约。
智能合约
contract Coin
//声明一个合约叫Coin
{
//关键字“public”使变量能从合约外部访问。
address public minter;//一个地址变量叫做 minter address类型的值大小为160 bits,不支持任何算术操作,适用于存储合约的地址或其他人的公私钥,没有public关键字的变量将无法被其他合约访问。
mapping (address => uint) public balances; //一个映射 mapping 通过address 能得到一个uint的balances的余额 mapping可以被认为是一个哈希表,每一个可能的key对应的value被虚拟的初始化为全0.这个类比不是很严谨,对于一个mapping,无法获取一个包含其所有key或者value的链表。所以我们得自己记着添加了哪些东西到mapping中。更好的方式是维护一个这样的链表,或者使用其他更高级的数据类型。或者只在不受这个缺陷影响的场景中使用mapping
//事件让轻客户端能高效的对变化做出反应。
event Sent(address from, address to, uint amount);
//声明一个事件
//这个构造函数的代码仅仅只在合约创建的时候被运行。
function Coin() {
minter = msg.sender;
}
//声明一个构造函数 Coin 在合约创建的时候被调用
function mint(address receiver, uint amount) {
if (msg.sender != minter) return;
balances[receiver] += amount;
}
//mint函数
function send(address receiver, uint amount) {
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Sent(msg.sender, receiver, amount);
}
//send函数 转账的交易
}
外部账户的地址是由公钥决定的,合约账户的地址是在创建该合约时确定的(这个地址由合约创建者的地址和该地址发出过的交易数量计算得到,地址发出过的交易数量也被称作"nonce")
安装solidity
solidity实例
Voting投票
contract Ballot
{
struct Voter
//定义了一个结构体类型
{
uint weight;//累积的权重
bool voted;//是否已经进行过投票
address delegate;//委托投票权
uint vote;//投票选择的提案索引号
}
struct Proposal
{
bytes32 name;//提案的名字
uint voteCount;//投票累积的数量
}
//最初定义结构体
address public chairperson;//定义了address状态变量,记住address相当于一个地址就行
mapping(address=>Voter) public Voters;//mapping相当于一个数组又相当于一个函数,给address与Voter进行了绑定
Proposal[] public proposals;//声明一个proposal的数组叫做proposals,智能合约中的数组起名相当于想要的数组数+s形成该变量
//的数组
//定义了状态变量
function Ballot(bytes32 proposalName){//构造函数,需要传入bytes32位的合约名字
chairperson = msg.sender;//合约的调用者就是 msg.sender
voters[chairperson].weight=1;
//对提供的每一个提案的名称,创建一个新的提案
//将对象添加到数组末尾
for(uint i = 0;i<proposalName.length;i++){
proposals.push(Proposal({
name:proposalName[i],
voteCount:0
}));
}
}
function giveRightToVote(address voter){//需要给一个地址,才能调用这个函数,相当于赋予其投票权力
if(msg.sender!=chairperson||voters[voter].voted){
throw;
//throw会终止和撤销所有的状态和以太改变
//如果函数调用无效,这通常是一个好的选择
//但是注意,这会消耗提供的gas
voters[voter].weigt=1;
}
}
function delegate(address to){
//指定引用
Voter sender = voters[msg.sender];
if(sender.voted)
throw;
while(voters[to].delegate!=address(0)&&voters[to].delegate!=msg.sender)
to=voters[to].delegate;
if(to==msg.sender)
throw;
//因为sender是一个引用,
//这里实际修改了voters[msg.sender].voted
sender.voted=true;
sender.delegate=to;
Voter delegate =voters[to];
if(delegate.voted){
proposals[delegate.vote].voteCount+=sender.weight;
else
delegate.weight +=sender.weight;
}
}
function vote(uint proposal){//进行投票,选取你想要去的项目进行投票
Voter sender =voters[msg.sender];//进行引用sender是当前投票的voter
if(sender.voted)throw
sender.voted=true;
sender.vote=proposal;
//如果proposal索引超出了给定的提案数组范围
//将会自动抛出异常,并撤销所有的改变
proposals[proposal].voteCount+=sender.weight;
}
function winningProposal()constant return(uint winningProposal){
uint winningVoteCount = 0;
for(uint =0 ;p<proposals.length;p++){
if(proposals[p].voteCount>winningVoteCount){
winningVoteCount =proposals[p].voteCount;
winningProposal=p;
}
}
}
}
源文件的布局
Solidity支持import语句,非常类似JavaScript(ES6),虽然Solidity不知道“缺省导出”的概念
在全局的层次上,你可以使用下列形式使用import语句
import "filename";
合约的结构
Solidity的合约和面向对象语言中的类的定义相似。每个合约包括了 状态变量,函数,函数修饰符,事件,结构类型 和枚举类型。另外,合约也可以从其他合约中继承 。
状态变量是在合约存贮器中永久存贮的值
函数是合约中可执行单位的代码
函数修饰符可以在声明的方式中补充函数的语义
事件是和EVM(以太虚拟机)日志设施的方便的接口
结构是一组用户定义的变量
枚举是用来创建一个特定值的集合的类型
类型
solidity是一种静态语言,类似于脚本语言,意思是每个变量(声明和本地)在编译时刻都要定义
布尔类型:只有真与假
还有操作符: !(非) &&(逻辑与) ||(逻辑或) ==(相等) !=(不等)
操作符||和&&可以应用常规短路规则
整形
int和uint:是有符号和无符号的整数,关键字uint8刀uint256步长(8到256位的无符号整数)
uint和int 分别是uint256和int256 的别名
地址:address 20字节(一个ethereum地址),地址的类型也可以有成员
账户余额balance和发送send
字符串常量:bytes 或者是String
枚举是一种solidity中的创建一个用户定义的类型。枚举类型中的枚举值可显示转换,但是从整数类型隐式转换是不允许的
数组:数组是可以在编译时固定大小的,也可以是动态的。对于存储器数组来说,成员类型可以是任意的(也可以是其他数组,映射或结构)。对于内存数组来说 ,成员类型不能是一个映射;如果是公开可见的函数参数,成员类型是必须是ABI类型的。
length是长度,push是方法与es6一样
结构体:struct
映射:映射类型被声明为 mapping _KeyType => _ValueType, _KeyType可以是除了映射以外的其他任何类型,_ValueType可以是任何类型,包括映射。
块和交易属性
block.coinbase (address): :当前块的矿工的地址
block.difficulty (uint):当前块的难度系数
block.gaslimit (uint):当前块汽油限量
block.number (uint):当前块编号
block.blockhash (function(uint) returns (bytes32)):指定块的哈希值——最新的256个块的哈希值
block.timestamp (uint):当前块的时间戳
msg.data (bytes):完整的calldata
msg.gas (uint):剩余的汽油
msg.sender (address):消息的发送方(当前调用)
msg.sig (bytes4):calldata的前四个字节(即函数标识符)
msg.value (uint):所发送的消息中wei的数量
now (uint):当前块时间戳(block.timestamp的别名)
tx.gasprice (uint):交易的汽油价格
tx.origin (address):交易发送方(完整的调用链)
合约
Solidity里的合约是面向对象语言里的类。它们持久存放在状态变量和函数中,(在里面)可以修改这些变量。在不同的合约(实例)中调用一个函数(的过程),(实际上)是在EVM(Ether虚拟机)中完成一次调用,并且完成(一次)上下文切换,(此时)状态变量是不可访问的。