Solidity学习笔记

1、Solidity特性

相较于javaScript

  • 新增address类型;
  • 语言内嵌框架支持支付;提供了payable等关键字,可以在语言层面直接支持支付;
  • 使用区块链进行数据存储。数据的每个状态都可以永久存储,所以再使用时需要确定变量使用内存,还是区块链存储;
  • 运行环境实在去中心化的网络上,所以需要强调合约或函数执行的调用方式
  • 不同的异常机制。一旦出现异常,所有的执行都将回回撤,这主要是保证合约执行的原子性,避免中间状态的出现的数据不一致;

2、Solidity关键字

  • pragma:杂注,在合约文件最上方。pragma solidity ^版本号;
  • address payable:与地址类型基本相同,不过多了transfersend两个成员变量。address payable可以隐式的转换为address,而address无法转换为address payable
  • view:指明函数只读不写,可以从链上读取数据,但不能往链上写数据;
  • constant:与view相同,一般只修饰状态变量,不允许赋值(除初始化以外)
  • pure:指明函数是一个纯计算的函数,不能从链上读取数据,只能读取临时变量;
  • public:公开类型,如果属性设置为public类型,则自动生成一个get函数,外部可以访问;
  • constructor:构造函数,在部署合约时给变量赋初始值;
  • mapping(address => uint):go中的map类型
  • eventevent配合emit使用,使用event定于一个事件,在调用的时候添加emit,在外部就可以监控,放在函数内部似使用。
  • assert:断言,必须为true
  • enum:枚举,不能在函数内部定义,应该在合约内部定义。枚举类型可以转换为任意整型
  • fixed/ufixed:浮点类型,常用fixed128x20,其中128为总长度,小数位长度为20
  • bytes1/bytes2 ……:定长字节数组,里面存储的是16进制数据不是utf8类型,用的时候注意转换
  • 对于存储型(storage)的数组来说,元素类型可以是任意的(即元素也可以是数组类型,映射类型或者结构体);对于内存型(memory)的数组来说,元素类型不能是映射(mapping)类型
  • msg.sender.transfer:要给msg.sender发送
  • 高维数组定义的时候跟go是反着的,例如,一个由5个uint动态数组组成的数组是uint[][5],访问的时候跟go相同,例如,要访问第三个动态数组中的第二个uint,可以使用x[2][1],越界访问将导致调用失败回退。增加新元素,必须使用.push()或者将.length增大,变长的storage数组和bytes(不包括string)有一个push()方法。
  • 所有的复杂类型,即数组、结构体和映射类型,都有一个额外属性,“数据位置”,用来说明数据是保存在内存memory中还是存储storage
  • immutable可以在合约部署时,定义常量;

3、数据位置

  • 函数参数(包括返回的参数)的数据位置默认都是memory,局部变量的数据位置默认是storage,状态变量的数据位置强制是storage。另外还存在第三种数据位置calldata这是一块只读的,且不会永远存储的位置,用来存储函数参数。外部函数的参数(非返回参数)的数据位置被强制指定为calldata,效果跟memory差不多。

3.1 数据位置总结

强制指定的数据位置

  • 外部函数的参数(不包括返回参数):calldata
  • 状态变量:storage

默认数据位置

  • 函数参数(包括返回参数):memory
  • 引用类型的局部变量:storage
  • 值类型的局部变量:栈(stack)
    特别要求
  • 公开可见(publicly visible)的函数参数一定是memory类型,如果要求是storage类型则必须是private或者internal函数,这是为了防止随意的公开调用占用资源

4、回退函数(fallback)

  • 回退函数(fallback function)是合约中的特殊函数;没有名字,不能有参数也不能有返回值
  • 如果在一个合约的调用中,没有其他函数与给定的函数标识符匹配(或没有提供调用数据),那么这个函数(fallback函数)会被执行
  • 每当合约收到以太币(没有任何数据),回退函数就会执行。此外,为了接受以太币,fallback函数必须标记为payable。如果不存在这样的函数,则合约不能通过常规交易接受以太币(给合约纯转账)
  • 在上下文中通常只有很少的gas可以用来完成回退函数的调用,所以使fallback函数的调用尽量廉价很重要
  • 回退函数可以使用fallback()receive()调用
    在这里插入图片描述

在这里插入图片描述

如果调用合约中不存在的方法,首先判断msg.data是否为空,如果不为空则调用fallback函数,如果为空则判断是否有receive方法,如果存在receive方法则调用receive,否则调用fallback函数
在这里插入图片描述

5、memory和storage之间的赋值

在这里插入图片描述

  • storagememory之间是值拷贝;
  • 其他类型向storage都是值拷贝;
  • memorymemory之间是指针拷贝;
  • storagelocal storage之间是指针拷贝;
  • storage是状态变量,它的修改会改变链上数据memory是局部变量,函数调用结束后会被销毁;
  • 在合约内定义在函数外定义的是状态变量。在函数内定义的只有函数调用时才会创建,并不会改变链上数据;

6、使用了view依然可以修改

在这里插入图片描述
要深入理解
在这里插入图片描述
view:只能从合约上读取数据
pure:既不读取,也不存储,只是进行运算;

7、delete的用法

在这里插入图片描述
在这里插入图片描述

8、调用合约的Gas消耗

在这里插入图片描述

9、函数可见性

public修饰的变量和函数,任何用户或者合约都能调用和访问(可以被当前合约调用、被继承被外部调用)。
external 与public 类似,只不过这些函数只能在合约之外调用 - 它们不能被合约内的其他函数调用(只能被外部调用,不能被继承不能被内部调用)。

internal 和 private 类似,可以被继承合约调用。
private修饰的变量和函数,只能在其所在的合约中调用和访问,不能被继承合约调用。

10、数组

在这里插入图片描述

  • 定义局部变量的数组时,因为要开辟内存,所以必须指定数组长度,例如:uint[] memory a = new uint[](5)
  • 局部变量的数组不能使用pushpop等命令,只能通过下标修改;
  • 如果入参中有数组类型,需要指定memory或者calldata类型(和memory类似,但是只能用于参数中)。使用calldata类型时,两个函数直接可以直接传递参数时会节约gas;

11、继承

  • 父合约中需要被重写的方法需要使用关键字virtual,子合约中重写函数中使用关键字override
  • 多线继承需要注意父合约顺序,越基础的越靠前。如果多重继承中需要重写,需要在函数override关键字后面加上(x,y)
    在这里插入图片描述
    在这里插入图片描述
  • 继承中的构造函数
    在这里插入图片描述
  • 继承中调用父合约的方法。一种是合约名.方法名另一种是super.方法名 super会自动寻找父合约。如果使用super.方法名,方法在多重父合约中都重写了,会依次调用(出栈顺序 子->父->祖)
    在这里插入图片描述

12、合约之间调用

在这里插入图片描述

  • 合约类型(合约地址).方法名

13、Hash运算

keccak256:智能合约中进行hash运算
abi.encode:进行bytes类型的打包,会使用0补齐,更加安全
abi.encodePacker:进行bytes类型的打包,不会使用0补齐。会出现碰撞,例如"AA","BB""A","ABB"的结果是一样的
ecrecover:会恢复签名结果,验证签名

14、节约gas

  • 将入参的存储位置关键字从memory改为calldata
  • 将循环体中的i += 1 替换为 ++i
  • 需要重复读写的数据先存储到局部变量,最后写入状态变量

15、transfer、send、call

  • transfer:带有2300个Gas,如果失败会调用reverts
  • send:带有2300个Gas,返回一个bool值表示是否发送成功
  • call:发送所有的Gas,返回一个bool值表示是否发送成功和返回data。如果发送地址是一个智能合约,则通过data带回
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值