(代码编辑器没有solidity高亮因此选择了JavaScript)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
contract HellWeb3{
string public name = 'helloweb3World';
}部署就可以看到这个合约上公开的name值
contract HellWeb3{
bool public b = true;
uint public u = 123;//unit = uint256 还有uint8 uint16
int public i = -123;//支持正数和负数
int public minInt = type(int).min;//int的最小值
int public maxInt = type(int).max;//int的最大值
//solidity中最特殊的变量--地址
address public addr = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
address public addd = 0x0000000000000000000000000000000000000000;
//不需要双引号 如果是双引号不就是字符了嘛
//除了地址还有bytes 比地址长一些了
bytes32 public b32 = 0x00000000000000000000000000000000;
}contract FunctionIntro{
//定义一个加法方法
function add(uint x,uint y) external pure returns (uint){
return x + y;
}
//external标记函数只能在外部读取
//pure标记不消化gas 纯函数 不对链上有任何操作
//returns 返回后接类型
//定义减法方法
function sub(uint x,uint y) external pure returns (uint){
return x - y;
}
}contract StateVriables{
//状态变量
uint public myUint = 123;
function foo() external pure {
//局部变量 非状态变量
uint notStateVriables = 456;
notStateVriables = 123;
}
}contract GlobslVariables{
//全局变量
function globalVars() external view returns(address,uint,uint){
address sender = msg.sender;//调用这个函数的地址 上一个调用该函数
uint timeStamp = block.timestamp;//区块的时间戳
uint blockNum = block.number;//区块编号
return (sender,timeStamp,blockNum);
}
}contract ViewAndPureFuntions{
uint public num;
function viewFunc() external view returns (uint){
return num;
}//只要去读取了连上的信息 必须要使用view
function pureFunc() external pure returns (uint){
return 1;
}//纯函数
function addToNum(uint x) external view returns (uint){
return num + x;
}//只读取了
function add(uint x,uint y) external pure returns (uint){
return y + x;
}//纯
}contract Counter{
uint public count;
//写入方法
function inc() external {
count +=1;
}
function dec() external {
count -=1;
}
}contract DefaultValues{
//变量默认值
bool public b;//false
uint public u;//0
int public i;//0
address public a ;//0x00000000000000...
bytes32 public b32;//0x0000000000000000...
}不需要修改的值用常量定义 可以节省gas
contract Constants{
//常量 constant
address public constant MY_ADDR = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;//消耗373gas
uint public constant MY_UINT = 123;
}
contract Var {
address public MY_ADDRESS = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;//消耗2483gas
}contract IfElse{
function example(uint x) external pure returns (uint){
//三目运算
bool b = x<10 ?true:false;
b = false;
if(x < 10){
return 1;
}else if(x < 20){
return 2;
}else{
return 3;
}
}
}contract ForAndWhile{
function loops() external pure {
for (uint i = 0; i < 10; i++) {
if(i == 3){
continue ;
}
if(i == 5){
break;
}
}
uint j = 0;
while (j < 10){//while(true)无限循环在智能合约中不允许
j++;
}
}
function sum(uint n) external pure returns (uint){
uint s;
for (uint i = 1; i <= n; i++) {
s += i;
}
return s;
}//在区块链中尽量减少这个循环 不然一直累加会耗费很多gas
}contract ErrorExm {
function testRequire(uint i) public pure{
//条件报错 满足条件时报错
require(i>=10, "i > 10 Must1");
//直接报错
if(i<=10){
revert("i >10 Must2");
}
}
uint public num = 1233;
function testAssert() public view{
assert(num == 123);
}//断言报错无自定义信息
//如果报错之后之前消耗的gas会退还
//自定义报错的字符串过长会造成gas浪费
//自定义错误 节省gas
error MyError(address caller,uint i);
function testCustomEorror(uint i) public view{
if(i > 10){
revert MyError(msg.sender,i);
}
}
}contract FuncModify{
bool public paused;
uint public count;
function setPause(bool _paused) external {
paused = _paused;
}
//自定义函数修改器
modifier whenNotPaused(){
require(!paused, "pasused");
_; //标记应用修改器函数的代码位置
}
//没用修改器直接写之前
function inc() external {
require(!paused, "pasused");
count += 1;
}
function dec() external {
require(!paused, "pasused");
count -= 1;
}
//应用修改器之后和上面两一样
function incM() external whenNotPaused {
count += 1;
}
function decM() external whenNotPaused{
count -= 1;
}
//带参数的修改器
modifier cap (uint _x){
require(_x<100,"x>= 100");
_;
}
function incBy(uint _x) external whenNotPaused cap(_x){
count += _x;
} //先执行whenNotPaused的代码 然后再把参数带入cap的修改器执行 在执行本函数代码
//三明治方式修改器
modifier sandWich(){
count += 10;
_;//中间运行
count *= 2;
}
function foo() external sandWich{
count +=1;
}
}构造函数仅仅只在合约部署的时候进行调用一次 之后再也不能被调用了
contract Constructor{
//构造函数
address public owner;
uint public x;
constructor(uint _x){
owner = msg.sender;
x = _x;
}
}contract Ownable{
address public owner;
constructor(){
owner = msg.sender;
}
modifier onlyOwner(){
require(msg.sender == owner,"not owner");
_;
}//函数修改器 确认是不是当前用户
function setOwner(address _newOwner) external onlyOwner{
require(_newOwner != address(0),"invalid address");
owner = _newOwner;
}//设置新当前用户
function onlyOwnerCanCallThisFunc() external onlyOwner{
}
function anyOneCanCall() external {
}
}contract FuncOutputs{
//返回值只标记数据类型
function returnMany() public pure returns(uint,bool){
return (1,true);
}
//返回值标记数据类型和值名
function returnManyByName() public pure returns(uint x,bool b){
return (1,true);
}
//隐式返回
function assigned() public pure returns(uint x,bool b){
x = 1;
b = true;
//等同于return (1,true);
}
//合约中调用函数接收返回值
function putAssigned() public pure{
//返回值都接收
(uint x ,bool b) = returnMany();
//只接收某一个
(,bool _b) = returnMany();
}
}contract Array{
//动态数组
uint[] public nums = [1,2];
//定长数组
uint[3] public nums1 = [1,2,3];
//数组推入数据
function examples() external {
nums.push(4);//只有动态数组可以用push推入数据 定长数组不可以
nums[1];//通过数组的索引访问数组中的值
nums[2] = 666;//通过数组的索引修改数组中的值
delete nums[1];//删除不会修改数组的长度 之后改成默认值0
nums.pop();//弹出数组最后一个值
nums.length;//获取数组的长度
//在内存中创建数组 在内存中不能创建动态数组
uint[] memory a = new uint[](5);
a[1] = 123;
}
//返回数组的全部内容
function returnArray() external view returns (uint[] memory){
return nums;
}
}contract ArrayShift{
uint[] public arr;
function example() public {
arr = [1,2,3];
delete arr[1];//根据索引删除的时候 会将这个第二个元素重置为默认值0
//但是通常情况下我们想要的是数组删除这个元素之后 这个元素直接随之消失 数组长度也发生改变
// [1,2,3] -> [1,0,3] -> [1,3]
}
function remove(uint _index) public {
require(_index < arr.length,"index out of bound");
for (uint i = _index; i < arr.length -1 ; i++) {
arr[i] = arr[i + 1];//从删除的地方开始把数据往左移动 然后再把最后一个空位弹出
}
arr.pop();
}
function test() external {
arr = [1,2,3,4,5];
}
function testR() external view returns (uint[] memory){
return arr;
}
//上面这种循环移动位置的方式删除数组元素消耗的gas太多了
//所以可以通过替换之后删除数组元素 但是这种方式缺点是打乱数组顺序
function removeBySet(uint _index) external {
arr[_index] = arr[arr.length-1];
arr.pop();//[1,2,3] index = 1; arr[1] = arr[2]; [1,3,3]; 然后把最后一个3弹出
//这个简单来说就是把要删除的索引的值 赋值成最后一个 这样最后一个获得了替换保留 那么他就被替换 然后原替换者也被弹出了
}
}contract Mapping{
//映射
mapping (address => uint) public balances;//key地址 value余额 (value = 映射变量名[key] )
//嵌套映射
mapping (address => mapping(address => bool) ) public isFriend;
function example() external {
// uint bal = balances[msg.sender]; //取值
balances[msg.sender] = 123;//这个地址的人有了余额为123
balances[msg.sender] += 456;
}
function lookingMap() external {
// value = balances[_add];
uint bal2 = balances[address(1)]; //获取默认值
balances[msg.sender] = bal2;
}
}contract IterableMapping{
mapping (address => uint) public balances;//余额
mapping (address => bool) public inserted;//标记是否存在映射中 (已存在)
address[] public keys;
//数组方便遍历 map方便映射 两种结合可迭代映射
function set(address _key,uint _val) external {
balances[_key] = _val;
if(!inserted[_key]){
inserted[_key] = true;
keys.push(_key);
}
}
function getSize() external view returns (uint){
return keys.length;
}
function first() external view returns (uint){
return balances[keys[0]];
}
}contract Structs{
struct Car{
string model;
uint year;
address owner;
}
Car public car;
Car[] public cars;
mapping (address => Car[]) public carsByOwner;
function examples() external {
Car memory toyota = Car("XiaoMinGW",1999,msg.sender);//构造结构体对象
Car memory lambo = Car({year: 1999,model:"LaLaLa",owner:msg.sender});//根据不同顺序的参数构造结构体对象
Car memory tesla;
tesla.model = "TES";//构造结构体对象后参数一一赋值
tesla.year = 2024;
tesla.owner = msg.sender;
cars.push(toyota);
cars.push(lambo);
cars.push(tesla);
cars.push(Car("ZZ" ,2000 ,msg.sender ));
//memory 内存中
//storage 存储 带有指针式读取可修改变量
Car storage _car = cars[0];
car.year = 1555;
//删除
delete _car.owner;
delete cars[1];
}
}contract Enum{
enum Status{
None,//枚举类型的默认值就是第一个
Pending,
Shipped,
Completed,
Rejected,
Canceled
}
Status public status;
struct Order{
address buyer;
Status status;
}
Order[] public orders;
function get() view external returns (Status){
return status;
}
function set(Status _status) external {
status = _status;
}
function ship() external {
status = Status.Shipped;
}
function reset() external {
delete status;
}
}原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。