以太坊智能合约学习笔记(二)

错误检查

  • 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;

【以太坊智能合约学习笔记(二)】未完成,待更新...

    推荐阅读