Solidity 合约开发要掌握的特性和关键词记录

Solidity 合约开发要掌握的特性和关键词记录

    • 1.入门扫盲
      • 常用的关键词
      • 用过的一些方法
      • 记录一些特别的操作
      • 记录常用的[OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts)安全审查后的合约库
    • 2.省Gas秘籍
      • 利用view特性
      • 结构封装(Struct packing)

最近看了一些Solidity开发资料,目前latest是0.6.12,记性不好,记录一下。

1.入门扫盲

常用的关键词

变量相关 类型 备注
uint 无符号整数 uint 默认为 uint256的缩写
mapping 映射 键值对存储key/val,可嵌套
address 地址类型 一般是两种类型:用户或者合约,自带成员函数 transfer 和 send等,更多成员函数
struct 结构体 可以有多个属性,类似Go的struct
enum 枚举 通常由多个常量值构成的自定义类型
storage 引用类型 永久存储在链上,类似硬盘
memory 引用类型 临时存储,外部函数对某合约调用完时回收,类似内存
calldata 引用类型 只读,用来存储函数传的参数,方便的在函数内引用而不占用空间。0.6.9之前只能外部调用
delete 初始化为0 Solidity没有null和undefined的概念,注意:delete数组某个索引后可能留空位置。
bytes 定长字节数组 类似byte[],bytes能“紧打包”,将元素连续存起来,意味使用Gas更低。
strings 特殊数组 与bytes相同,但不允许用长度或索引来访问。

更多请查看Solidity文档:全局变量 、保留关键字、修饰符、函数可见性 速查表

函数相关 类型 备注
event 事件 合约和区块链的通讯机制,前端可触发event方法做出反应。
emit 触发事件 事件的调用方法
indexed 事件索引 最多三个,特殊数据结构,前端能通过filter筛选事件,普通的是日志数据结构。
payable 函数类型 表示可以接受ETH的函数
Internal 函数类型 内部,类似private,继承关系可使用。
external 函数类型 外部,类似public,不能在继承关系中使用。
view 函数修饰符 表示函数只读不改,不会消耗Gas
pure 函数修饰符 表示函数只做计算不读不改,不会消耗Gas
virtual 函数类型 函数重写,接口默认会进行标记virtual,private不能使用该标记。
override 函数类型 函数重写,配合父合约标记的virtual函数使用
abstract 抽象合约 定于与现实分离,用于提高扩展性,消除代码重复
interface 接口 不实现任何函数,只制定接口,其他合约继承后需要实现
library 两种使用方法,一种是using for,一种是直接实例化,自动添加库所有方法给一个数据类型
is 继承 可用“,”多继承,存在钻石问题,注意顺序加载:base,base-A,base-A-A这样写。
import 导入 可以导入其他sol文件
constructor() 构造函数 初始化合约调用一次的函数
modifier 函数修饰符 修饰已有的函数,并且能自定义条件函数。
receive() 特殊函数 一个合约只有一个接收以太函数,在没有payable修饰符还转账情况下自动调用。
fallback() 回退函数 externall类型,调用不存在的函数时调用,但是转账类型交易如果不加payable会报异常。
全局变量 类型 备注
ether 费用单位 以太单位,类似还有wei、 finney、 szabo
Now 时间单位 当前时间戳,因为是32位,会有2038问题。类似还有seconds、minutes、hours、days、weeks、years(0.5.0因闰年已移除)
msg.sender 全局变量 当前调用者的address
msg.value 全局变量 当前交易的wei数量
tx.gasprice 全局变量 交易的 gas 价格
block.number 全局变量 当前区块号

更多请查看Solidity文档:特殊变量和函数

用过的一些方法

方法名 描述 备注
require() 错误处理 不满足条件就撤销更改,0.5版新增第二个参数可以抛出message
assert() 错误处理 和 require 类似,require失败会返回剩下的Gas,assert则不会,出现严重错误时使用。
keccak256() 数学和密码学函数 伪随机的散列函数,更多数学和密码学函数
uint8() 类型强转 uint8 c = a * uint8(b); 类似的有uint256,uint16,但是uint8不能转到uint256。
arr.push() 数组成员方法 在尾部加入新元素,类似的还有length、pop
生成随机数 0-100的随机数 非安全,可能被算力强的节点利用,只打包对自己有利的区块发布到链上:uint random = uint(keccak256(now, msg.sender, randNonce)) % 100

记录一些特别的操作

关键词 类型 备注
5 ** 2 乘方操作 x 的 y次方,5 ** 2 = 25
变量名含"_" 私有变量名 一种习惯,区别全局变量
public 函数修饰符 默认会提供getter方法
uint[] 动态数组 类似的有uint[10]固定数组,Person[]结构体数组
return (a,b,c) 函数参数和返回 批量返回函数值和接受值 跟 Go类似
_; 占位符 modifier中的_; 表示“被修饰的函数开始执行”
0x0 黑洞地址 没有私钥的地址,常用来烧币,主动报废一些token。

记录常用的OpenZeppelin安全审查后的合约库

库名 描述 备注
SafeMath 安全数学运算 可防止 overflow 和 underflow 的加减乘除
SafeCast 安全类型转换 和SafeMath类似,防止转换时的 overflow 和 underflow
Ownable 访问权限 合约的主人才可以调用哦
Roles 角色控制、访问层次 比Ownable多了个角色概念,可以进行权限分组了。
ERC20 代币标准 普通代币的一些定义
ERC721 代币标准 用于加密收藏品,有不可分割、不可互换、整单位交易等特性。
Address 地址检测 让我看看你是个合约,还是用户

具体描述参考:OpenZeppelin 7个最常使用的合约

2.省Gas秘籍

以太坊是去中心化的应用,为了防止某些用户无限循环,占用网络资源。每次执行Dapp都需要支付一定的Gas,Gas使用以太币购买。

利用view特性

view的定义是只读不改,不会真正改变链上任何数据。因此用户从外部调用一个view修饰的函数,不会产生任何Gas。

如果 一个 view 函数有进行 内部调用,虽然不属于同一个合约,但依旧会产生Gas。因为调用的函数会生成事务,要进行节点验证产生成本。所以只有外部调用view是免费的。

结构封装(Struct packing)

struct MiniMe {
  uint32 a;
  uint32 b;
  uint c;
}

在Struct里使用合适的uint类型,并且把同样类型的变量放一起(即在 struct 中将把变量按照类型依次放置), 这样能让Solidity空间最小化。

用uint8代替uint256并不会节省空间,因为Solidity会默认使用256保留。

参考:
https://learnblockchain.cn/docs/solidity/
https://cryptozombies.io/

你可能感兴趣的:(Solidity,Dapp,区块链,区块链)