solidity的一些特性

solidity的基本语法及使用参见官方文档

https://solidity.readthedocs.io/en/v0.4.25/

这里总结一些特别之处:

1. ABI编码
  例:函数 functionName(uint p1, address p2, bytes p3)
    则 函数签名 functionName(uint256,address,bytes)
       函数选择器 bytes4(keccak256("functionName(uint256,address,bytes)"))
     【注意】1. uint类的写法改为uint256
                    2. 没有空格,选择器取前4个字节
       调用合约函数及参数的序列化算法
       交易的data字段的前4个字节来做匹配,即函数选择
       函数选择器4个字节后紧挨着的是入参,每个入参一个word(32字节),但并不全是入参的编码,还可能是入参位置的编码(动态变量),即先把确定性变量和动态变量位置进行编码,再后面是动态变量的实际值的编码

2. 全局函数

blockhash(uint)   取最新的256个区块号对应的hash,但不包括当前区块的

block.coinbase/block.difficulty/block.gaslimit/block.number/block.timestamp/now 都是取当前区块的相关信息

gasleft() 交易带的gas值减去交易执行到现在的gas

msg.data  完整的calldata,ABI编码 字节数组

msg.sender/msg.sig(calldata前4个字节 函数选择器)/msg.value

tx.gasprice/tx.origin

3. 以太坊中的“消息”

message: gas  value  to  sender  data  code

消息调用就是找到to指向的账户地址的code(合约账户创建时最后的结果),然后用data的ABI编码匹配到相应的函数,然后输入入参,执行相应的函数

即基于账户的存储运行相应的代码

EVM代码中,如果有create/call/callcode/delegatecall/staticcall中的一个,就会产生child message,进而形成新的EVM Computation

执行中,memory:一维数组,前4个words固定,每个EVM Computation独立使用

              栈:初始的EVM Computation及后续的child message触发的EVM Computation同用的。

  4. 全局函数  ABI编码

abi.encode()    对指定的参数进行ABI编码

abi.encodePacked()  ABI编码并紧打包

abi.encodeWithSelector(bytes4,...) 从第2个参数开始进行ABI编码,并将第一个参数放在编码结果的前面作为前缀

abi.encodeWithSignature(string signature,...)  即abi.encodeWithSelector(bytes4(keccak256(signature), ...)

5. 全局函数 异常处理

assert(bool)  非预期错误,不返还gas,惩罚性质,很少使用

require(bool) 有条件检查,返还gas,原则上对所有输入数据的检查,或者计算结果的状态检查都用require,可以附加消息作为第2个参数

revert()  无条件直接返回异常,返还gas,可以附加消息作为第2个参数

6. 全局函数 算术函数

addmod(x,y,z)   ==》 (x + y) % z 

mulmod(x,y,z)   ==》 (x * y) % z 

超过2的256次方不会被舍弃

7. 全局函数 密码学函数

keccak256/sha3/sha256/ripemid160

ecrecover(hash, v, r, s)  由签名恢复公钥

8. 全局函数 地址相关

.balance

.transfer             2300gas限制,失败时抛出异常

.send                 2300gas限制 ,失败不抛出异常,只返回false

.call   传入ABI编码,对其调用,附加所有gas(可以.gas调整),失败返回false

.callcode 等价于call,但是保持执行上下文,即将目标地址相应的合约函数代码拷贝到当前合约中执行

.delegatecall. 等价于callcode, 但是会保持msg.sender msg.value

9. 全局修饰器

pure: function   不访问,不修改状态变量

view: function   可以访问,不修改状态变量

payable: function 函数调用可以附加以太币

constanct: state variable 状态变量除初始化外不允许赋值,也就是不占用存储空间,最终就是固定的合约代码

anongmous: event (收据 日志) 指明时间的签名不作为topic

indexed: event parameter 指明事件参数需要作为topic

10. event

event 事件是收据中的一个条目,合约执行的日志,

一个事件可以有5个topic和额外的若干个数据

topic 0固定是事件签名的keccak256 (不取4字节了), 除非事件被声明为anongmous

所有的topic都会被加入到交易和区块的bloomfilter 可以通过jsonrpc/web3的filter功能进行快速过滤匹配

《注》所有日志数据都是公开可见的,不只是indexed的

11.合约函数的可见性

private  internal public external

合约调用private/internal函数,本质上是代码跳转(标签跳转),不会产生calldata和returndata,内存是共用的,msg也保持不变,返回值直接在栈或者内存中传递

调用public函数,如果直接用函数名调用,等价于internal,用this.调用,等价于external函数,产生child message,会有calldata和returndata,所以public函数,如果本合约有内部调用时,会有两套处理代码

external函数,只能被外界调用,必定会产生calldata和returndata

12. 状态变量的可见性

private  internal public

13. 引用类型的数据位置

         可用位置                     局部变量默认

array  storage/memory           storage

struct storage/memory           storage

mapping  storage

14. fallback函数

fallback不处理输入,不返回返回值

通过transfer/send函数对合约地址转账,必须触发fallback函数,所以需要明确写明payable的fallback函数

                                  

 

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