智能合约(一)
bytes用来存储任意长度的字节数据,string用来存储任意长度的
(UTF-8编码)的字符串数据。
balance用来查询账户余额,transfer()用来发送以太币(以wei为单
位)。
一、数据类型
1、布尔类型(bool) true false
2、整形
int/uint: 表示有符号和无符号不同位数整数。支持关键字uint8到uint256 (以8步进),
uint 和 int 默认对应的是 uint256 和 int256。
整数除法总是截断的,但如果运算符是字面量(字面量稍后讲),则不会截断。
3、 定长字节数组
关键字有:bytes1, bytes2, bytes3, ..., bytes32。(以步长1递增)
byte代表bytes1。
bytes用来存储任意长度的字节数据,string用来存储任意长度的(UTF-8编码)的字符串数据。
如果长度可以确定,尽量使用定长的如byte1到byte32中的一个,因为这样更省空间。
字符串常量与整数常量
注意:
定长字节数组:byte[7] aa = [byte(0x11),0x11,0x11,0x11,0x11,0x11,0x11];
变长字节整数:byte[] cc = new byte[](10);
存储在内存中的无论是定长还是变长都不能改变长度
4、十六进制常量
以关键字hex开头 如 hex"001122ff"
5、字符串常量
不可以用下标访问其中的某个字符,但可以通过将其转换为bytes数组形式访问。
6、枚举类型
在Solidity中,枚举可以用来自定义类型。它可以显示的转换与整数进行转换,但不能进行隐式转换。枚举至少应有一个成员。
7、地址类型 address
20字节
地址类型成员:
balance 属性及transfer() 函数这里是地址类型相关成员的快速索引balance用来查询账户余额,transfer()用来发送以太币(以wei为单位)
send()函数:
send 与transfer对应,但更底层。如果执行失败,transfer不会因异常停止,而send会返回false
call()函数:返回一个bool值 , 参数为:
id = keccak256(�这里面是函数�)这样就可以生成函数id,然后就可以使用对应合约类的地址.call(第一参数是上面获取的id,以后的参数就是函数的参数)
匿名函数:
一个合约可以有一个匿名函数。此函数不能有参数,也不能有任何返回值。当我们企图去执行一个合约上没有的函数时,那么合约就会执行这个匿名函数。
此外,当合约在只收到以太币的时候,也会调用这个匿名函数,而且一般情况下只会消耗很少的gas,所以当你接受到以太币后,想要执行一些操作的话,你尽可以把你要的操作写到这个匿名函数里,因为这样做成本非常便宜。
function() public payable{}
构造函数先初始化,再调用构造函数
五、访问器函数
创建的状态变量为public时(uint public data = 10;),
会自动创建get函数 function data() external {}
只能以external方式访问
2、枚举访问器与上述访问方式相同
3、数组访问器 this.array(1) ; 要用小括号
4、映射访问器 带有参数 参数为键类型的
Mapping(uint => uint) public data ;
this.data(20); 20为键
5、结构体访问器 需要用变量接受结构体中的所有变量
var(a,b,c) = this.s();
Return (a,c);
智能合约(二)
memory : 内存中,数据不是永久存在
storage : 永久存贮在区块链中
memory 数组 不能改长度 无论是bytes 还是 uint
storage 可变数组 可以修改长度 无论是bytes 还是 uint
一、存储位置分析
1、数据位置
storage(永远存储在区块链中):引用类型,局部复杂变量(数组,数据结构)
状态变量
memory(内存中,不是永久存在):函数参数,简单局部变量
calldata(不会永久存储的一个数据位置):外部函数参数,不包括返回参数只是读的
storage 在区块链中是用key/value的形式存储,而memory则表现为字节数组
memory 只能用于函数内部,memory 声明用来告知EVM在运行时创建一块(固定大小)内存区域给变量使用
注意:
不能将memory 赋值给复杂局部变量。(不明白)
对于值类型,总是会进行拷贝。
一个storage的状态变量,赋值给一个storage的局部变量,是通过引用传递。所以对于局部变量的修改,同时会修改关联的状态变量。
将一个memory 的引用类型赋值给另一个 memory 的引用,不会创建拷
贝(即:memory 之间是引用传递)。
三种存储方式内存消耗
storage 会永久保存合约状态变量,开销最大
memory 仅保存临时变量,函数调用之后释放,开销很小
stack 保存很小的局部变量,几乎免费使用,但有数量限制。
二、数组的使用
初始化数组:
uint [] public u = [1,2,3];
uint[] memory m = new uint[](10);
Length:数组可以指定长度也可以是动态变长。
Data:数据类型可以是任意的
数组作为构造函数参数时:
如:bytes8[] _name 传参:["0x12","0x23","0x45"]
bytes与string区别:bytes提供length与set数据 而string不提供
三、结构体及映射
结构体内数据类型可以是任意的,也可以是结构体类型的,即支持结构体嵌套
初始化:
Add memory add = Add("beijing");
Person memory p1 = Person("List",30,add); //结构体不能用new
访问:p1.age = 40 ; //直接使用 . 访问
四、solidity常见单位
1、货币单位: 1 ether , 3 finney , 6 szabo , 18 wei ,
2、时间单位:secounds,minutes ...... now:表示现在距1970 多久
五、常见的API介绍
错误处理:
1、assert(bool condition)
用于判断内部错误,条件不满足时抛出异常
2、require(bool condition): (常用)
用于判断输入或外部组件错误,条件不满足时抛出异常
3、revert():
终止执行并还原改变的状态
<<以下内容能记住就记住,记不住就看看>>
数学及加密功能
1、addmod(uint x, uint y, uint k) returns (uint):
计算(x + y) % k,加法支持任意的精度且不会在2**256处溢出,从
0.5.0版本开始断言k != 0。
2、mulmod(uint x, uint y, uint k) returns (uint):
计算(x * y) % k, 乘法支持任意的精度且不会在2**256处溢出,
从0.5.0版本开始断言k != 0。
3、keccak256(...) returns (bytes32):
使用以太坊的(Keccak-256)计算HASH值。紧密打包参数。
4、sha256(...) returns (bytes32):
使用SHA-256计算hash值,紧密打包参数。
5、sha3(...) returns (bytes32):
keccak256的别名
6、ripemd160(...) returns (bytes20):
使用RIPEMD-160计算HASH值。紧密打包参数。
7、ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns
(address):
通过椭圆曲线签名来恢复与公钥关联的地址,或者在错误时返回零。
可用于签名数据的校验,如果返回结果是签名者的公匙地址,那么说明数
据是正确的。
地址相关
1、 balance (uint256):
Address的余额,以wei为单位。
2、 transfer(uint256 amount):
发送给定数量的ether到某个地址,以wei为单位。失败时抛出异常。
3、send(uint256 amount) returns (bool):
发送给定数量的ether到某个地址,以wei为单位, 失败时返回false。
4、 call(...) returns (bool):
发起底层的call调用。失败时返回false。
5、callcode(...) returns (bool):
发起底层的callcode调用,失败时返回false。
不鼓励使用,未来可能会移除。
6、 delegatecall(...) returns (bool):
发起底层的delegatecall调用,失败时返回false
合约相关
1、this(当前合约的类型):
表示当前合约,可以显式的转换为Address
2、selfdestruct(address recipient):
销毁当前合约,并把它所有资金发送到给定的地址。
3、suicide(address recipient):
selfdestruct的别名
另外,当前合约里的所有函数均可支持调用,包括当前函数本身。