以太坊智能合约开发(二):Solidity编程基础
1 sol文件结构
1.1 编译开关
编译开关 pragma solidity ^0.6.0; ,该编译开关表明编译器版本需要高于0.6.0才可以编译。也可以指定编译器的版本范围:pragma solidity >= 0.6.0 < 0.7.0;
1.2 引用其他源文件
全局引入:import "filename"; 。 自定义命名空间引入符号“*”:import * as symbolName from "filename"; 。 分别定义引入:import {symbol1 as alias,symbol2} form "filename"; .
1.3 合约
pragma solidity ^0.6.0;
contract hello {
string public name;
constructor() public {
name = "hello";
}
}
这里的contract可以理解为一个类。contact有构造函数、成员函数和成员变量。
1.4 库
库和合约的区别在于库不能有Fallback函数以及payable关键字,同时也不可以定义storage变量,但是库可以修改和他们链接的合约的storage变量。
1.5 接口
与java、C++一样,solidity接口只定义行为,没有实现。
2 合约文件结构
一个合约一般包括以下组成部分:
- 状态变量(State variables)
- 结构定义(Structure definitions)
- 修饰符定义(Modifier definitions)
- 事件声明(Event declaration)
- 枚举定义(Enumeration definitions)
- 函数定义(Function definitions)
3 变量类型
3.1 值类型
(1)布尔型:值为true或者false。 (2)整型:int或者uint。 (3)地址:以太坊的地址(address)的长度大小为20B,160bit。 (4)定长字节数组:固定大小的字节数组。 (5)有理数和整型字面量。 (6)枚举类型:solidity中的一种用户自定义类型,它可以显式地与整型进行转化,但不能进行隐式转换。 (7)函数:
- 函数可以将函数值给一个变量,该变量即为一个函数类型的变量。
- 还可以将一个函数作为参数进行传递。
- 也可以在函数调用中返回一个函数。
完整的函数定义为:
function <name>(<parameter types>){internal|external}[constant][payable][returns(<return type>)]
若不说明函数类型,默认函数类型为internal。如果函数没有返回值,则省略return关键字。 函数可以分为内部函数(internal)和外部函数(exinternal)。内部函数只能在当前合约内被使用,不能在当前合约的上下文环境以外的地方执行。如在当前的代码块内,包括内部库函数和继承的函数中,函数的默认类型就是internal。外部函数由地址和函数方法签名两部分组成。可作为外部函数调用的参数或者外部函数调用的返回。
3.2 引用类型
(1)不定长字节数组:不定长字节数组是一个动态数组,能够容纳任意长度的字节。Bytes可以声明为一个设定长度的状态变量:bytes localBytes = new bytes(0); ,Bytes也可直接赋值:localBytes = "this is a test"; ,元素可以被压缩入字节数组:localBytes.push(byte(10)); (2)字符串:在C语言中,字符串以“\0”结尾,在solidity中,字符串并不包含结束符。 (3)数组:可使用new关键字创建一个memory的数组。与storage的数组不同,不能用.length的长度来修改数组的大小属性。
pragma solidity ^0.4.0;
contract test1{
function fun (){
uint [] memory A = new uint[](7); //创建一个memory的数组
}
uint[] B;
function fun2 (){
B = new uint[](7);
B.length = 10;
B[9]=100;
}
}
(4)结构体:结构体是用来实现用户定义的数据类型。结构是一个组合数据类型,包含多个不同数据类型的变量。但结构体里没有任何代码,仅仅由变量构成。struct funder {address addr;uint amount;} 。结构体目前仅支持在合约内使用,如果在参数和返回值中使用结构体,函数必须声明internal。
4 操作语句
solidity不支持switch和goto语句。
4.1 条件语句
与传统语句一样,solidity同样支持if/else语句。需要注意if(1){…}在solidity中是无效的。
4.2 循环语句
循环语句while和for语句。
uint insertIndex = stack.length;
while(insertIndex > 0 && bid.limit <=stack[insertIndex-1].limit){
insertIndex--;
}
4.3 其他
(1)break:用来跳出现有的循环。 (2)continue:用来退出当前的循环。 (3)return:用来从函数/方法中返回。 (4)?::三元操作符。如a>b? a:b,如果a>b返回a,否则返回b。
5 类型转换
Solidity同样支持类型转换,例如,将一个数字字符串转换为整型或浮点数。转换被分为隐式类型转换和显式类型转换。
5.1 隐式类型转换
如果运算符支持两种不同的类型,那么编译器会尝试隐式类型转换,同理赋值时也是类似。通常,隐式类型转换要保证不丢失数据且语义通顺。例如uin8可以转换为uint256,int8不能转为uint256,因为uint不支持-1。任何无符号整数都可以转换为相同或更大长度的字节数组,任何可以转换为uint16的类型,也可以转换为address类型。
function add() public pure returns (uint){
uint8 i = 10;
uint16 j = 20;
uint16 k = i + j;
return k;
}
在运行uint16 k= i+j运算时,i会隐式转换为uint16,在return k时,k会隐式转换为uint256。
5.2 显式转换
如果编译器不允许隐式的自动转换,但你知道转换没有问题时,可以进行显式类型转换。
6 Solidity中的单位
6.1 货币单位
一个数字常量后面跟随一个后缀 wei, funney,szabo或ether,这个后缀就是货币单位。
6.2 时间单位
一个数字常量后面跟随一个后缀seconds,minutes,hours,days,weeks,years,这个后缀就是时间单位。
|