BlockChain入门-Solidity基础语法
01-入门
1 2 3 4
| pragma solidity ^0.8.21 contract HelloWeb3{ string public _string="Hello Web3!"; }
|
第一行注释不写会出现警告。
第二行指编译器版本不允许小于0.8.21,“^”表示不允许编译器版本大于等于0.9.0。
第三行创建string
型变量_string
。
02-变量类型
1 2 3 4 5 6 7
| int uint uint256 string bool address //20字节 address payable byte32 byte8 byte1 ! && || == != //&&运算符短路
|
03-函数
关键字pure
标记的函数不能读写链上状态,不消耗gas fee。
1 2 3
| function addPure(uint256 _number)external pure returns(uint256 new_number){ new_number=_number+1; }
|
关键字view
只能读不能改写,不消耗gas fee。
1 2 3
| function addView()external view returns(uint256 new_number){ new_number=number+1; }
|
关键字internal
标记的函数只能被该合约内其他函数调用,不能被外界调用。
1 2 3
| function minus()internal{ number=number-1; }
|
关键字external
标记的函数只能在该合约外被调用,不能被该合约内其他函数调用:
1 2 3
| function minusCall()external{ minus(); }
|
关键字payable
标记的函数能够接受Remix的“VALUE”的转账。
1 2 3 4
| function minusPayable()external payable returns(uint256 balance){ minus(); balance=address(this).balance; //返回当前合约的余额 }
|
关键字public
标记的函数从内部和外部都可见,private
只能从内部访问且继承的合约也不能使用。
04-函数输出
多个返回值:
1 2 3
| function returnMultiple()public pure returns(uint256,bool,uint256[3] memory){ return(1,true,[uint256(1),2,5]); }
|
命名式返回,仍可用return
:
1 2 3 4 5
| function returnNamed()public pure returns(uint256 _number,bool _bool,uint256[3] memory _array){ _number=2; _bool=false; _array=[uint256(3),2,1]; }
|
解构式赋值:
1 2 3 4 5 6
| uint256 _number; bool _bool; uint256[3] memory _array; (_number,_bool,_array)=returnNamed(); //不读的留空 (,_bool,)=returnNamed();
|
05-变量数据存储和作用域(未完)
数据位置:
storage
:默认状态,存储在链上,消耗gas fee多。
memory
:函数的参数和临时变量一般用这个,存储在内存中,不上链,消耗gas fee少。当string、bytes、array和自定义结构等返回数据类型变长的情况下必须加memory
。
calldata
:存储在内存中,不上链,不能修改,一般用于函数参数。
1 2 3
| function fCalldata(uint[] calldata _x)public pure returns(uint[] calldata){ return(_x); }
|
当状态变量storage
赋值给本地storage
时,以及memory
赋值给memory
时,会创建引用,类似指针。其他情况均创建副本。
1 2 3 4 5
| uint[] x=[1,2,3]; function fStorage()public{ uint[] storage xStorage=x; xStorage[0]=100; //状态变量x[0]也被同时更改 }
|
常见全局变量:
address payable msg.sender
表示消息发送者,即当前的调用者。
06-引用类型、数组、结构体
数组:
1 2 3 4 5 6 7 8 9 10 11 12
| //固定长度数组 uint[8] array1; bytes1[5] array2; address[100] array3; //可变长度/动态数组 uint[] array4; bytes1[] array5; address[] array6; bytes array7; //特殊 bytes本身就是数组 比bytes1[]省gas fee //memory动态数组 声明长度后不能更改 uint[] memory array8=new uint[](5); bytes memory array9=new bytes(9);
|
数组字面常数:
1 2 3 4 5 6 7 8
| contract C{ function f()public pure{ g([uint(1),2,3]); //所有元类型与第一个元素为准 } function g(uint[3] memory _data)public pure{ //... } }
|
创建动态数组时需要一个个元素赋值:
1 2 3 4
| uint[] memory x=new uint[](3); x[0]=1; x[1]=3; x[2]=4;
|
数组成员:
1 2 3 4
| a.length; //返回数组长度 a.push(); //动态数组专有 最后添加一个0 并返回该元素的引用 a.push(x); //动态数组专有 最后添加一个x a.pop(); //动态数组专有 移出数组最后一个元素
|
结构体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| struct Student{ uint256 id; uint256 score; } Student student; function initStudent1()external{ Student storage _student=student; _student.id=11; _student.score=100; } function initStudent2()external{ student.id=1; student.score=80; } function initStudent3()external{ student=Student(3,90); } function initStudent4()external{ student=Student({id:4,score:60}); }
|
09-常数
const
必须在声明的时候初始化,之后不能改变。immutable
可以在声明时和构造函数中初始化。
1 2
| uint256 constant CONSTANT_NUM=10; uint256 public immutable IMMUTABLE_NUM=9999999999;
|
10-控制流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| function ifElseTest(uint256 _number)public pure returns(bool){ if(_number==0){ return(true); } else{ return(false); } } function forLoopTest()public pure returns(uint256){ uint sum=0; for(uint i=0;i<10;i++){ sum+=i; } return(sum); } function whileTest()public pure returns(uint256){ uint sum=0; uint i=0; while(i<10){ sum+=i; i++; } return(sum); } function doWhileTest()public pure returns(uint256){ uint sum=0; uint i=0; do{ sum+=i; i++; }while(i<10); return(sum); } function ternaryTest(uint256 x,uint256 y)public pure returns(uint256){ return x>=y?x:y; } //存在continue和break关键字
|
11-构造函数&修饰器(未完)
1 2 3 4 5 6 7
| modifier onlyOwner{ require(msg.sender==owner); //检查调用者地址是否为owner _; //是的话继续运行函数主体,否则报错并revert交易 } function changeOwner(address _newOwner)external onlyOwner{ owner=_newOwner; //只有owner地址运行这个函数并改变owner }
|
12-事件(未完)
事件声明与释放:
1 2 3 4 5 6 7
| event Transfer(address indexed from,address indexed to,uint256 value); //定义Transfer事件 function _transfer(address from,address to,uint256 amount)external{ _balances[from]=10000000; //给转账地址一些初始代币 _balances[from]-=amount; //from地址减去转账数量 _balances[to]+=amout; //to地址加上转账数量 emit Transfer(from,to,amount); //释放事件 }
|