solidity8基础
权限修饰符
public:内部、外部可见
internal:内部可见(当前文件内),不能用 this 调用。
external:仅在外部可见(仅可修饰函数),即使在合约内,也只能通过this.
private:仅在当前合约可见
全局变量
//常用全局变量
//链id
uint id = block.chainid;
//区块号
uint num = block.number;
//时间戳
uint time = block.timestamp;
//剩余 gas
uint gas = gasleft();
//调用者地址
address sender = msg.sender;
//发送的主币数量
uint value = msg.value;
//完整的 calldata 数据
bytes memory data = msg.data;
//calldata的前 4 个字节
bytes4 sig = msg.sig ;
//指定块的区块hash - 仅最近 256 个区块有效
bytes32 a = blockhash(12);
//当前合约地址
address add = address(this);
view 和 pure
//view: 函数不会修改合约变量,只读,不消耗燃料
//pure: 纯函数,不读写合约变量,只操作函数变量,不消耗燃料,可用于算法计算
function getNum() public view returns(uint8){
return num + 1;
}
function gettNum(uint8 _num) public pure returns(uint8){
return _num + 1;
}
存储memory、storage和calldata
引用类型包括结构,数组和映射,使用引用类型,必须明确指明数据存储位置
string类型实际上是bytes,也属于数组
memory:即数据在内存中,因此数据仅在其生命周期内(函数调用期间)有效。不能用于外部调用。
storage:状态变量保存的位置,只要合约存在就一直存储.
calldata:用来保存函数参数的特殊数据位置,是一个只读位置。
常用数据类型
整型
int:有符号整型,支持int8、int16...int256,8位为步长递增,int默认为int256,默认值为0
uint:无符号整型,支持uint8、uint16...uint256,8位为步长递增,uint默认为uint256,默认值为0
支持 加减乘除、大于小于等于,移位运算和大部分语言相同,不记录
uint a = 10**5;//幂运算 10的五次方 100000
布尔型
bool a;//默认值为false
浮点型
fixed:有符号定长浮点型,支持fixedMxN,fixed默认fixed128x19
ufixed:无符号定长浮点型,支持ufixedMxN,ufixed默认ufixed128x19
M 表示该类型占用的位数,N 表示可用的小数位数,M必须能整除8,即8到256位。N可以是从0到80之间的任意数
枚举类型
enum Names {
TOM,
Jack,
ROSE
}
Names name;
function getName() public view returns(Names){
return name;
}
function setName() public {
name = Names.ROSE;
}
地址类型
address owner;
映射
mapping(address => bool) data;
function get() public view returns(bool a){
a = data[msg.sender];
}
function set(bool _b) public {
data[msg.sender] = _b;
}
数组
//动态数组
uint[] a = [1,2,3];
function push(uint _num) public {
a.push(_num);
}
function get() public view returns(uint[] memory) {
return a;
}
//删除末尾元素
function pop() public {
a.pop();
}
//删除指定位置元素,只是变为0,不会改变数组长度
function del(uint _ind) public {
require(_ind <= a.length -1, "index out of bound");
delete a[_ind];
}
//获取数组长度
function getLength() public view returns(uint l){
l = a.length;
}
//内存数组必须是定长数组,不能修改长度,也不能用push和pop方法
function test() public pure returns(uint[] memory){
uint[] memory list = new uint[](3);
list[0] = 1;
list[1] = 3;
list[2] = 6;
//uint[3] memory list1 = [uint(1),3,6];
return list;
}
结构体
struct Cat{
string name;
uint8 age;
}
Cat public tom;
function set() public {
tom = Cat({
name: "aaa",
age: 18
});
}
function get() public view returns(Cat memory){
return tom;
}
常量&不可变量
//constant:常量,值在编译时确定
uint public constant a = 10;
//immutable:不可变量,值在部署时确定
uint public immutable a = 10;
//gas费比较
uint public a = 10; //114253 gas
uint public constant a = 10; //91875 gas
uint public immutable a = 10; //98492 gas
uint public immutable a; //101013 gas
constructor(uint _a){
a = _a;
}
异常处理
require
function tes(uint _a) public pure {
require(_a > 10, "_a <= 10");
}
revert
function tes1(uint _a) public pure {
if(_a <= 10){
revert("_a <= 10");
}
}
assert
function tes2(uint _a) public pure {
assert(_a > 10);
}
error
error myError(string msg);
function tes3(uint _a) public pure {
if(_a <= 10){
revert myError("_a <= 10");
}
}
构造函数
address owner;
string name;
//部署时执行,且只会被执行一次
constructor(string memory _name){
owner = msg.sender;
name = _name;
}
函数修改器 modifier
bool paused;
// 函数修改器
modifier whenNotPaused(){
require(!paused,"paused");
_; //运行到此处会返回调用方函数继续执行
}
function tes() public whenNotPaused(){
}
继承 is
//virtual 父合约标记
//override 重写父合约
contract A {
function tes() public pure virtual returns (string memory) {
return "A";
}
function tes1() public pure virtual returns (string memory) {
return "A";
}
}
contract B is A{
function tes() public pure override returns (string memory) {
return "B";
}
function tes1() public pure virtual override returns (string memory) {
return "B";
}
constructor(string memory _name){
}
}
contract C is B{
function tes1() public pure override returns (string memory) {
return "C";
}
//向父合约构造函数传递参数
constructor(string memory _name, string memory memo) B(_name) {
}
}