错误检查
-
throw
: 抛出异常。已被废弃。 -
revert()
: 抛出异常,并回滚到调用前的状态。 -
require(bool)
:require(false)
抛出异常,并回滚到调用前的状态,并返回剩余的 gas。用于检查有效条件,比如检查函数输入和返回、检查调用者(require(msg.sender == owner)
)。 -
assert(bool)
: 。assert(false)
抛出异常,并回滚到调用前的状态,并消耗掉所有的 gas。用于检查内部错误(internal errors),比如上溢和下溢。可以利用消耗掉所有的 gas的特性,防止或者惩罚恶意攻击。
if(true){
// 抛出异常,不往下走
throw;
}
if(true){
// 抛出异常,不往下走
revert();
}
// 抛出异常,不往下走
require(false);
// 抛出异常,不往下走
assert(false);
数组
数组(Arrays):相同类型的元素的集合所组成的数据结构。
数组类型:
- 固定长度数组。
uint[5] dynamicArr
- 动态长度数组。
uint[] fixedArr
成员:
-
length
。 固定长度数组为声明时的长度,动态长度数组为数组中含有多少元素。 -
push
。往动态长度数组中增加一个元素,固定长度数组没有该方法。
// 声明
uint[] dynamicArr;
uint[3] fixedArr;
// 创建数组
uint[] dynamicArr = new uint[](7); // 赋值长度为 7 的动态长度数组
uint[3] fixedArr = new uint[3](); // 报错
uint[3] fixedArr = [1, 2, 3]; // 赋值长度为 3 的固定长度数组
// 成员赋值
dynamicArr[0] = 1;
fixedArr[0] = 1;
fixedArr[3] = 1; // 报错
// push 新元素
dynamicArr.push(1); // 正确
fixedArr.push(1); // 报错。fixedArr 没有 push 属性。
// 访问元素
dynamicArr[1]; // 0
fixedArr[1]; // 2
// 获取数组长度
dynamicArr.length; // push 新元素后,长度为 7+1。
fixedArr.length // 3
// 改变数组长度
dynamicArr.length = dynamicArr.length - 1; // 正确
fixedArr.length = fixedArr.length - 1; // 报错。不能改变固定长度数组的长度
// 遍历数组
for(uint i; i < dynamicArr.length; i++){}
for(uint i; i < fixedArr.length; i++){}
// 固定长度数组转换为动态长度数组。由于语言完善的问题,支持状态变量之间的转换,未来可能会取消该限制。
uint[] x = [1, 3, 4]; // 正确。
uint[] memory x = [1, 3, 4]; // 报错。固定长度 memory 的数组,不能转换为动态长度 memory 的数组。
结构体
结构体(Structs): 结构体是一些元素的集合。合法元素类型包括:值类型、数组和映射等,不包括:结构体。
// 声明
struc Employee{ // 大写 E
address id;
uint salary;
uint lastPayDay;
}
// 创建结构体
Employee employee = Employee(0x1, 0, 0);
// 访问成员
employee.id
数据存储
- storage 持久性
- memory 临时空间
- calldata 类似 memory,执行完后被抹除
相同存储空间赋值
- 传递引用 reference(EVM 上的内存地址)。 storage = storage
不同存储空间变量赋值
- 拷贝
memory a = storage ,b 在 memory 内存中重新开辟一个空间给 employee 类型,并且将 employee 这个值拷贝到 memory 内存空间中。将 memory 内存地址赋值给 memory 变量。所以 memory 变量内存地址并不是指向 storage 内存地址,而是一个 memory 变量的全新的地址。同样的将 memory 赋值给 storage 变量,也会进行一个拷贝。注意,只能将 memory 变量赋值给状态变量,而不是本地 storage 变量。因为我们只能在状态变量中分配内存空间。
delete
delete 初始化变量、删除数组中的内容
http://www.tryblockchain.org/...
@黄敏之-助教; EVM的定义就是0值等同于回收,把一个storage设为0是消耗负值的gas
实验结果: remove约等于remove2,同时远远小于remove3和4。且执行完remove12后下次remove34的gas消耗大大增加。这个很有意思。1和2做的都是释放内存的操作,所以有负gas的福利;释放内存后如果要再赋值,需要重新申请内存,所以这样会消耗更多的gas。
delete owner
delete arr 初始化arr length =0
delete arr[i] 初始化 arr 的某个元素,但此时 arr[i] 还占据空间,length 也没有变。
// 因此需要以下两步,真正的删除元素
arr[i] = arr[arr.length - 1]
arr.lenght -= 1;
未完成,待更新...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。