Solidity学习笔记一:基础语法与remix的使用

  • Yuanwai
  • 更新于 2023-08-21 16:48
  • 阅读 2913

越学越迷糊,于是准备再学一遍,进行总结。Solidity学习笔记一:基础语法与remix的使用


theme: nico highlight: a11y-dark

本人是一只前端程序猿,最近各种前端已死的言论甚嚣尘上,既然web2走不通了,那就去web3这条赛道瞧瞧

参加了登链社区技术集训营二期,又看了其他的教学视频,感觉是越学越迷糊

image.png

于是准备再学一遍,进行总结。如有错误,还请指正🫰希望各位大佬能够不吝赐教

Solidity:是一门面向合约的、为实现智能合约而创建的高级编程语言。

智能合约:是管理以太坊状态里账户行为的程序。

Solidity 是静态类型语言,支持继承、库和复杂的用户定义类型等特性。

1、 从编辑器开始

万事开头难,我们先拿编辑器开个头

编写Solidity有很多种方式,我们先用浏览器的在线编辑器,比较简单,访问这个在线编辑器网站 Remix 编辑器

第一步就是先把其他的文件给删除掉,

image.png

第二步:新建自己的contracts文件夹 ,然后在里面新建一个以 .sol 结尾的文件 (智能合约的文件都是以.sol结尾的)

image.png

2、运行起来

代码要先指明 solidity 使用的版本

pragma solidity 0.8.7; // 只是用这个版本

solidity版本也有几种不同的声明方式

pragma solidity 0.8.7; // 只是用这个版本

pragma solidity ^0.8.7; // 比0.8.7这个版本更新的都适用

pragma solidity >0.8.7; // 大于这个版本
pragma solidity >=0.8.7 <0.9.0; // 大于等于这个版本适用  0.9以上的不适用

重点: 每行代码都要使用 ; 结尾

你以为 pragma solidity 0.8.7; 就是web3的第一行代码了吗?

no ! no ! no ! no ! no !

在开始写程序之前 需要先声明一下,否则在有的编辑环境下有可能会报错

它是定义一个代码规则和分享规则

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

在编辑器里,你写的代码就是这个样式

然后进行编译,点击Compile ...是进行编译;没有语法错误编译成功时,1处就会有个绿色的对号

image.png

到这 已经把 Solidity 项目运行起来了,虽然好像什么都没有,但是确实 实实在在的编译成功了

接下来咱们继续,开始深入

3、合约内容

俗话说:万事开头难,然后中间难;现在开始学习智能合约,开始填充合约内容

合约是使用 contract 进行声明的

它就像一个java语言的class一样,声明一个合约名

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract HelloWorld{
// 合约内容
}

数据类型

在Solidity中的变量类型大概分为这几类

  1. 数值类型(Value Type) :包括布尔型,整数型等等,这类变量赋值时候直接传递数值。

  2. 引用类型(Reference Type) :包括数组和结构体,这类变量占空间大,赋值时候直接传递地址(类似指针)。

  3. 映射类型(Mapping Type)Solidity里的哈希表。

数值类型

数值类型 最基础的有四种数据类型分别是 boolean , uint , int , address 等等

boolean // 布尔值类型 默认值为false

int // 可表示正数和负数 默认值为0

uint // uint是无符号整数 表示这个数字不是可正可负的,就只能表示正数 默认值为0

string // 表示一个单词,字符串,需要用 “”

address // 表示地址 比如数字钱包的地址 默认值为0的地址: 0x0000000000000000000000000000000000000000

enum //枚举

boolean

// SPDX-License-Identifier: MIT
pragma solidity 0.8.8;

contract HelloWorld {
    // 定义一个变量名为 hasFavoriteNumber 的布尔值
    bool hasFavoriteNumber = true;
}

uint

uint是无符号整数 表示这个数字是正整数

而且 solidity里也没有小数

// SPDX-License-Identifier: MIT
pragma solidity 0.8.8;

contract HelloWorld {
    // 定义一个变量名为 favoriteNumber 的正数
    uint favoriteNumber; // 初始化值为0
    uint favoriteNumber1 = 666;

    // 我们可以给unit分配空间 uint8表示他有8个bit,uint就相当于uint256
    uint8 favoriteNumber = 255;
    uint favoriteNumber = 666; // 默认分配的空间大小就是256
    uint256 favoriteNumber = 666; 
}

但是如果我给 unit8 赋值一个比较大的数字,那么就会报错

因为赋值的数字已经超过了unit8可以存储的范围

image.png

enum 枚举

枚举(enum)是solidity中用户定义的数据类型。它主要用于为uint分配名称,使程序易于阅读和维护,使用名称来代替从0开始的uint

// 用enum将uint 0, 1, 2表示为Buy, Hold, Sell  
enum ActionSet { Buy, Hold, Sell }  
// 创建enum变量 action  
ActionSet action = ActionSet.Buy;

int

可表示正数和负数 默认值为0

// SPDX-License-Identifier: MIT
pragma solidity 0.8.8;

contract HelloWorld {
    // int
    int favoriteInt = -5; 

    int256 favoriteNumber = 666;
}

string

表示一个字符串

// SPDX-License-Identifier: MIT
pragma solidity 0.8.8;

contract HelloWorld {
    // string类型
    string favoriteText = "dong";
}

address

表示地址 比如数字钱包的地址

// SPDX-License-Identifier: MIT
pragma solidity 0.8.8;

contract HelloWorld {
     // address类型
    address myAddress = 0xb2028c070948d7F42FB1e0465dcB70F0671A155d;
}

bytes

// SPDX-License-Identifier: MIT
pragma solidity 0.8.8;

contract HelloWorld {
     // bytes类型 也可以制定大小  它通常存储以 0x开头后面跟一些随机数字和字母
    bytes32 favoriteBytes = 0x3f89
    // bytes 赋值字符串类型 会自动转化为bytes  32是它允许分配的最多的空间
    bytes32 favoriteBytes = "cat"
}

定义一个常量

常量: 在变量名前面 加上 constant 标识 , 常量名用大写字母表示

// SPDX-License-Identifier: MIT
pragma solidity 0.8.8;

contract HelloWorld {
  address public constant MY_ADDRESS;

}

细心的同学可以发现,定义变量的时候在变量名前面有一个 public

public :表示这个变量公开了,任何与合约交互的人 都可以看到 变量中存储的值

我们定义两个变量,一个带有public,一个不带,接下来我们把它部署一下

// SPDX-License-Identifier: MIT 
pragma solidity ^0.8.7;

// 第一个合约
contract SimpleStorage {
    uint myNumber = 111;
    uint public favoriteNumber = 666;
}

编译好后,我们点击 1 这个时候就进入编译的页面,按钮2:"Deploy" 就是部署

image.png

点击 Deploy 按钮 就会发现部署好后的操作区域,可以看到有public的显示在页面上,我们能看到,没有public标识的就没有公开

image.png

接下来点击一下它就能看到它的值

image.png

引用类型

引用类型(Reference Type) :包括数组和结构体,这类变量占空间大,赋值时候直接传递地址(类似指针)。

数组

数组: 如果你想建立一个集合,可以用 数组 这样的数据类型. Solidity 支持两种数组: 静态数组和 动态数组:

// 固定长度为2的 uint类型的静态数组:
uint[2] fixedArray;
// 固定长度为5的 string类型的 静态数组:
string[5] stringArray;
// 动态数组,长度不固定,可以动态添加元素:
uint[] dynamicArray;

结构体

struct 结构体:支持通过构造结构体的形式定义新的类型;声明一个自定义的类型

// 结构体  
struct Student{  
    uint256 id;  
    uint256 score;  
}
Student student; // 初始一个student结构体

以下是对数组和结构体的总结

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

contract MyContract{
    // 定义一个类型,类型名为People
    struct People{
        uint256 favoriteNumber;
        string name;
    }
    // 
    People public people=People({favoriteNumber:6,name:'dong'});
    People public people1=People({favoriteNumber:61,name:'dong1'});

  // 定义一个数组
    People[] public peopleList;
    // 向数组内添加数据
    function addPerson(string memory _name,uint256 _favoriteNumber) public{
        // 添加数据方式一
        People memory newPerson = People({favoriteNumber:_favoriteNumber, name:_name});
        peopleList.push(newPerson);

        // 方式二
        peopleList.push(People({favoriteNumber:_favoriteNumber, name:_name}));
    }
}

函数

Solidity里的函数我觉得和JS的函数非常相似,他也是用function关键字声明的,但是多了一些修饰符

  • function 函数名(参数)修饰符 {}

参数也需要声明类型

// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;

contract SimpleStorage {
    uint256 public favoriteNumber; // 以0初始化变量

    // 定义一个 store的函数 传入一个形参 
    function store(uint256 _favoriteNumber) public {
        // 进行赋值
        favoriteNumber = _favoriteNumber;
    }
}

image.png 点击黄色的 Deploy进行部署合约,就会出现以下信息

image.png

部署合约就 是发送一个交易;区块链上做任何事情,修改任何状态 就是在发一个交易, 我们可以在 store 里输入一个数字,然后点击 store按钮,就会调用一次合约会消耗一些gas

在变量名favoriteNumber前面添加一个 public 表示这个变量公开了,可以在外部访问到它,我们看看能不能赋值成功

image.png 点击favoriteNumber 可以看到已经赋值成功

函数和变量有 4 种可见度的标识符:

  • public表示公开,任何与合约交互的人 都可以看到 变量中存储的值(public会创建变量的getter函数,返回函数值)

  • private表示只对合约内部可见;只能从本合约内部访问,继承的合约也不能用(也可用于修饰状态变量)。

    
    uint[] numbers;

function _addToArray(uint _number) private { numbers.push(_number); }


   - `external`表示只对合约外部可见;只能从合约外部访问(但是可以用`this.fn()`来调用,`fn`是函数名)

   - `internal`表示只有这个合约或者继承它的合约可以读取;只能从合约内部访问,继承的合约可以用(也可用于修饰状态变量)。

### 函数权限/功能 关键字

 - `payable`(可支付的)很好理解,带着它的函数,运行的时候可以给合约转入`ETH`

- `view` 表示这个函数只会读取这个合约的状态,view函数里面不允许修改任何状态

- `pure` 也不允许修改状态,而且pure也不允许读取区块链数据,不能读取变量;通常用于某个不需要读取数据的算法

> **合约里面的操作和计算越多,消耗的gas也越多**

### 函数输出
`Solidity`的函数输出需要有两个关键字:`return`和`returns`

-   `returns`加在函数名后面,用于声明返回的变量类型及变量名;
-   `return`用于函数主体中,返回指定的变量。

```js
    // 返回多个变量
    function returnMultiple() public pure returns(uint256, bool, uint256[3] memory){
            return(1, true, [uint256(1),2,5]);
        }

命名式返回

returns 里表明返回的变量名称,solidity会自动初始化这些变量,并返回这些函数的值;并且不需要使用 return

    // 命名式返回
    function returnNamed() public pure returns(uint256 _number, bool _bool, 
    uint256[3] memory _array){
        _number = 2;
        _bool = false; 
        _array = [uint256(3),2,1];
    }

英语

英文 翻译
Compile 编绎;编译文件;编译
contract 合同;合约;契约;
private 私有的;私人的;私用的;
external 外部的;外面的;外界的;
internal 里面的;体内的;
点赞 3
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

2 条评论

请先 登录 后评论
Yuanwai
Yuanwai
0x94b1...8EFE
距离成为百年老程序员还差97年;公众号:oldCode