solidity语言学习

ouo

最近了解了点区块链的知识,先学学基础语言吧

source /root/.bashrc

一,前期准备

首先你需要一个IDE,编写solidity智能合约一般使用的是Remix IDE,因为下desktop折磨了半天还是失败了,所以只能用网页版了www。在一个Solidity智能合约中,你首先需要明确Solidity的使用版本,它应该被标注在Solidity代码的最上面,Solidity是一个更新频率很高的语言。所以我们需要告诉代码,要用哪个版本,我们通过Pragma Solidity + 版本号;来确定版本号

版本号有这么一些书写方式:

^0.8.0:表示支持0.8.0及以上的版本(同 >= 0.8.0)

0.8.22:表示只支持0.8.22版本

同时,在代码最上方,你可以加入SPDX-License-Identifier,最然这个是可选的,但是没有的话,有些编译器会出现警告。因为MIT是限制最少的License之一,我们会在大多数的代码中使用MIT协议。

二,开始

接下来,我们输入contract,开始定义智能合约,contract是Solidity的关键字,它告诉编译器后面的代码是来定义智能合约的。

就像这样。

1
2
3
4
5
6
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract test{

}

三,数据类型

solidity中数据类型有八种。

Solidity中的数据类型可以归纳为以下八种核心类型,每种类型的具体描述如下:


1. 布尔类型(bool

  • 用途:表示逻辑值 truefalse

  • 示例

    1
    bool isActive = true;

2. 整数类型

  • 分类

    • 有符号整数int8, int16, …, int256(步长为8,默认 intint256)。
    • 无符号整数uint8, uint16, …, uint256(默认 uintuint256)。
  • 用途:存储整数值,支持算术运算。

  • 示例

    1
    2
    uint256 balance = 1000;
    int32 temperature = -5;

3. 地址类型(address

  • 分类

    • 普通地址address,用于存储以太坊账户地址。
    • 可支付地址address payable,允许接收以太币(如 payable(msg.sender))。
  • 示例

    1
    2
    address user = 0x123...;
    address payable recipient = payable(user);

4. 固定大小字节数组(bytes1bytes32

  • 用途:存储固定长度的二进制数据(如哈希值)。

  • 示例

    1
    bytes32 hash = keccak256(abi.encodePacked("data"));

5. 动态大小字节数组(bytes

  • 用途:存储可变长度的二进制数据。

  • 示例

    1
    bytes data = hex"00112233";

6. 字符串类型(string

  • 用途:存储UTF-8编码的文本数据。

  • 示例

    1
    string greeting = "Hello, World!";

7. 固定点数类型(fixed/ufixed

  • 分类

    • 有符号固定小数:如 fixed128x18(128位总位数,18位小数)。
    • 无符号固定小数:如 ufixed128x18
  • 用途:高精度小数计算(实际使用较少)。

  • 示例

    1
    ufixed128x18 price = 3.1415;

8. 枚举类型(enum

  • 用途:定义一组命名的常量值。

  • 示例

    1
    2
    enum Status { Pending, Approved, Rejected }
    Status public currentStatus = Status.Pending;

一些数据类型的默认值

定义一个变量时,无论是局部变量还是状态变量(全局变量),都有自己的默认值,不同的是局部变量在声明时不会自动被赋予默认值,而是由开发者手动初始化。而状态变量在合约部署时会被自动赋予默认值。我们如果要部署后看到其默认值,就需要定义变量时加上public,例如

1
2
3
4
5
6
7
8
9
10
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract test{
uint public myuint;
bool public myBool;
address public myAddress;
string public myString;
uint[] public myArray;
}

编译部署后,我们就可以看到各自的默认值。

OSLRcx.png

四,函数

在solidity中,函数用function进行表示。举个栗子。我们定义一个catch函数。这个函数会把number改成一个新的值,要改变的数字,是传给catch函数的参数,所以我们定义catch函数,接受uint256的参数,参数名字是cnumber,定义为public函数,然后在函数中,我们将favoriteNumber赋值为传入的参数。

就像这样

1
2
3
4
5
6
7
8
9
10
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract test{
uint256 number;
function cat(uint256 cnumber) public {
number=cnumber;

}
}

不过有一点注意一下,自己定义函数时要注意避免使用solidity的保留字,比如abstract,catch,try,receive,fallback,interface,library,override 等。此时我们编译后部署就可以看到

OSL4Mj.png

我们在右边的框内输入数字就可以传到number里,但是我们在更改传入的数字时是看不到number值的变化的,这个时候就要引入可见度标识符的概念。

五,可见度标识符

函数和变量有四种可见度标识符public、private、internal和external。

public:public 是最高级别的可见度标识符,表示变量、函数或合约对内外部都可见。公共状态变量可以被任何人读取,并且公共函数可以被外部调用者调用。公共函数和状态变量的访问可以通过合约地址直接进行。
private:private 是最低级别的可见度标识符,表示只有当前合约内的其他函数才能访问该变量或函数。私有状态变量只能在当前合约中访问,私有函数只能被当前合约的其他函数调用。私有状态变量和函数对外部调用者是不可见的。
internal:internal 表示内部可见性,表示只有当前合约及其派生合约内的其他函数才能访问该变量或函数。内部状态变量和函数可以在当前合约及其派生合约中访问,但对外部调用者不可见。
external:external 可以用于函数,表示该函数只能通过外部消息调用。外部函数只能被其他合约调用,而不能在当前合约内部直接调用。此外,外部函数不能访问合约的状态变量,只能通过参数和返回值进行数据交互。
如果没有显式指定变量的访问修饰符,则默认为internal,而internal关键字表示,它只对本合约和继承合约可见。

现在这个number变量被设置为了internal,所以我们看不到它。

为了让我们看到它,我们需要更改其可见度。现在把它设置为public重新编译。

如下

1
2
3
4
5
6
7
8
9
10
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract test{
uint256 public number;
function cat(uint256 cnumber) public {
number=cnumber;

}
}

部署后就可以点number查看变量的值了。

OSLLXY.png

六,状态变量和局部变量

感觉就是全局变量和局部变量,函数外面的是全局变量(状态变量),函数里面的是局部变量。在函数内部声明的变量,其作用域只在函数内。作用域决定了函数和变量的可见性。所以其实很重要。举个错误例子.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract test{
uint256 public number;
function cat(uint256 cnumber) public {
number=cnumber;
uint256 vv=5;

}
function something()public{
uint256 vv=6;
}


}