3.1 Solidity前导知识
1. pragma-编译指示器
pragma solidity ^0.4.0;
2. import-引用文件指令
import "filename";
import * as symbolName from "filename";
import {symboll as alias, symbol2} from "filename";
import "filename" as symbolName;
3. 注释
//单行
/* ... */多行
3.2 智能合约的基本构成
3.2.1 状态变量
contract SimpleStorage {
uint storedData;
//......
}
3.2.2 函数
contract SimpleAuction {
function bid() public payable {
// ......
}
3.2.3 函数修饰器
当"_"符号出现在函数修饰器代码逻辑前面时,表示在被修饰函数的逻辑执行之后才执行函数修饰器的代码逻辑。
modifier onlySeller() {
require(
msg.sender == seller,
"Only seller can call this."
);
_;
}
3.2.4 事件
写入区块链日志的数据信息,在合约的开头首先要声明写入日志的数据类型,然后在具体的执行函数中,触发事件并将数据写入合约的日志存储空间。
contract SimpleAuction {
event HighestBidIncreased(address bidder, uint amount); //事件原型
function bid() public payable {
// ......
emit HighestBidIncreased(msg.sender, msg.value); //触发事件
}
}
3.2.5 结构体
struct Voter {
uint weight;
bool voted;
address delegate;
uint vote;
}
3.2.6 枚举类型
enum State { Created, Locked, Inactive }
3.3 Solidity 数据结构
优先级 | 操作描述 | 操作符号 |
1 | 后置自增、后置自减 | ++、-- |
new | new<typename> | |
数组下标 | <array>[<index>] | |
成员变量引用 | <object>、<member> | |
函数调用 | <func>(<args...>) | |
中括号 | (<statement>) | |
2 | 前置自增、前置自减 | ++、-- |
一元减号 | - | |
一元操作 | delete | |
逻辑取反 | ! | |
二进制取反 | ~ | |
3 | 指数运算 | ** |
4 | 乘法、除法、取余 | *、/、% |
5 | 加法、减法 | +、- |
6 | 移位 | <<、>> |
7 | 位与 | & |
8 | 位异或 | ^ |
9 | 位或 | | |
10 | 不等式操作 | <、>、<=、>= |
11 | 等式操作 | ==、!= |
12 | 逻辑与 | && |
13 | 逻辑或 | || |
14 | 三元操作 | ?: |
15 | 赋值操作 | =、|=、^=、&=、<<=、>>=、+=、-=、*=、/=、%= |
16 | 逗号 | , |
3.3.1 值类型
- 布尔型(bool:true、false)
- 整型(int8~int256、uint8~uint256)
- 地址类型(address、address payable:都是20字节的以太坊地址)
<address>.balance (uint256) //查询余额 <address payable>.transfer (uint256 amount) //转移ETH <address payable>.send (uint256 amount) returns (bool) //转移ETH的底层接口 <address>.call(bytes memory) returns (bool, bytes memory) //底层调用函数 //底层调用函数 <address>.delegatecall(bytes memory) returns (bool, bytes memory) //底层调用函数 <address>.staticcall(bytes memory) returns (bool, bytes memory)
- 合约类型:用户定义的合约也是一种数据类型
- 固定长度的数组:byte(bytes1)、bytes2、bytes3...bytes32
- 字面常量:地址常量、有理数和整数常量、字符串常量、十六进制常量
- 枚举类型
- 函数类型
function (<parameter types>) {internal|external} [pure|view|payable] [returns (<return types>)]
3.3.2 引用类型
当前可用的引用类型的数据有:数组(array)、结构体(struct)、映射(mapping)。
存储位置分为3类:memory、storage、calldata
3.3.3 左值操作类型
delete a 相当于a=0
3.3.4 类型转换原则
类型转换分为隐式的类型转换和显式的类型转换。
3.4 全局变量和单位
3.4.1 单位
以太坊作为公链,ETH可以精确到小数点18位。
assert(1 Wei == 1);
assert(1 szabo == 1e12);
assert(1 finney == 1e15);
assert(1 ether == 1e18);
时间单位:seconds、minutes、hours、days、weeks
3.4.2 全局变量和函数
(1)区块链交易属性
blockhash(uint blockNumber) returns(bytes32) //根据编号查询区块HASH值
block.coinbase(address payable) //产生当前区块的矿工地址
block.difficulty(uint) //当前的区块难度值
block.gaslimit(uint) //当前区块的gaslimit值
block.number(uint) //当前区块的编号
block.timestamp(int) //当前区块的石建耀
gasleft() returns(uint256) //剩余的GAS值
msg.data(bytes calldata) //完整的calldata数据
msg.sender(address payable) //当前消息调用者的地址
msg.sig(bytes4) //calldata的前4字节
msg.value(uint) //伴随消息发送的代币数,以Wei为单位
now(uint) //当前区块的时间耀,是block.timestamp的别名
tx.gasprice(uint) //交易的GAS价格
tx.origin(address payable) //交易的发起者地址
(2)ABI编码及解码函数
abi.decode(bytes memory encodedData, (...)) returns(...) //解码传入数据
abi.encode(...) returns(bytes memory) //将传入的参数编码
abi.encodeWithSelector(bytes4 selector, ...) returns(bytes memory)
(3)异常处理
assert(bool condition) //当条件不满足时,产生一个无效指令,状态回滚
require(bool condition) //如果条件不满足,则恢复状态修改
require(bool condition, string memory message) //同上,增加错误消息提示
revert() //放弃当前的函数执行并放弃之前对状态的修改
revert(string memory reason) //同上,增加了放弃修改的原因提示
(4)数学及加密函数
addmod(uint x,uint y,uint k) returns(uint) //(x+y)%k
mulmod(uint x,uint y,uint k) returns(uint) //(x*y)%k
keccak256(bytes memory) returns(bytes32) //计算字节数组keccak-256哈希值
sha256(bytes memory) returns(bytes32) //计算字节数组SHA-256哈希值
ripemd160(bytes memory) returns(bytes20) //计算字节数组的RIPEMD-160哈希值
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns(address) //椭圆曲线签名中计算关于hash值得地址
(5)地址类型的成员属性
<address>.balance(uint256) //当前地址余额,以Wei为计算单位
<address payable>.transfer(uint256 amount) //发送amount数量的Wei给函数的调用地址
<address payable>.send(uint256 amount) returns(bool) //发送amount数量的Wei函数调用地址
<address>.call(bytes memory) returns(bool, bytes memory) //触发底层函数调用CALL,消耗GAS
<address>.delegatecall(bytes memory) returns(bool, bytes memory) //触发底层函数DELEGATECALL
<address>.staticcall(bytes memory) returns(bool, bytes memory) //触发底层函数STATICCALL
(6)合约相关属性
this //指代当前的智能合约
selfdestruct(address payable recipient) //销毁当前合约并将余额转还给参数指定的账户
3.5 控制逻辑与表达式
3.5.1 控制语句
if、else、while、do、for、break、continue、return
3.5.2 函数调用
(1)内部函数调用
(2)外部调用
(3)命名调用和匿名函数参数
(4)函数参数的省略
3.5.3 通过new关键字创建合约
一个合约可以通过new关键字来创建其他合约的实例,被调用合约的代码对于调用者来说必须是完全可见的。通过.value()函数来传递以太坊代币给被调用合约,但是无法限制GAS的使用数量。
D d= new D(4);
3.5.4 赋值
元组赋值
(uint x, ,uint y) = f();
3.5.5 作用范围与声明
每个变量初始化时都会有默认值,bool=false,uint和int=0
3.5.6 异常处理
Solidity使用状态回滚异常来处理错误,这些异常会撤销当前调用下的所有状态修改,同时给调用者标记一个错误。