Skip to content

Commit

Permalink
Merge branch 'AmazingAng:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
AmazingAng authored Nov 26, 2023
2 parents 7d98a48 + d398175 commit e0d6430
Show file tree
Hide file tree
Showing 40 changed files with 1,299 additions and 948 deletions.
2 changes: 1 addition & 1 deletion 01_HelloWeb3/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tags:

# WTF Solidity极简入门: 1. Hello Web3 (三行代码)

我最近在重新学solidity,巩固一下细节,也写一个“WTF Solidity极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。
我最近在重新学Solidity,巩固一下细节,也写一个“WTF Solidity极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。

推特:[@0xAA_Science](https://twitter.com/0xAA_Science)

Expand Down
85 changes: 49 additions & 36 deletions 02_ValueTypes/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tags:

# WTF Solidity极简入门: 2. 值类型

我最近在重新学solidity,巩固一下细节,也写一个“WTF Solidity极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。
我最近在重新学Solidity,巩固一下细节,也写一个“WTF Solidity极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。

推特:[@0xAA_Science](https://twitter.com/0xAA_Science)

Expand All @@ -19,6 +19,7 @@ tags:
-----

## Solidity中的变量类型

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

2. **引用类型(Reference Type)**:包括数组和结构体,这类变量占空间大,赋值时候直接传递地址(类似指针)。
Expand All @@ -28,12 +29,14 @@ tags:
我们将仅介绍常用类型,不常用的类型不会涉及,本篇将介绍值类型。

## 值类型

### 1. 布尔型

布尔型是二值变量,取值为 `true``false`

```solidity
// 布尔值
bool public _bool = true;
// 布尔值
bool public _bool = true;
```

布尔值的运算符包括:
Expand All @@ -45,44 +48,46 @@ tags:
- `!=` (不等于)

```solidity
// 布尔运算
bool public _bool1 = !_bool; // 取非
bool public _bool2 = _bool && _bool1; // 与
bool public _bool3 = _bool || _bool1; // 或
bool public _bool4 = _bool == _bool1; // 相等
bool public _bool5 = _bool != _bool1; // 不相等
// 布尔运算
bool public _bool1 = !_bool; // 取非
bool public _bool2 = _bool && _bool1; // 与
bool public _bool3 = _bool || _bool1; // 或
bool public _bool4 = _bool == _bool1; // 相等
bool public _bool5 = _bool != _bool1; // 不相等
```

在上述代码中:变量 `_bool` 的取值是 `true``_bool1``_bool` 的非,为 `false``_bool && _bool1``false``_bool || _bool1``true``_bool == _bool1``false``_bool != _bool1``true`

**值得注意的是:**`&&``||` 运算符遵循短路规则,这意味着,假如存在 `f(x) || g(y)` 的表达式,如果 `f(x)``true``g(y)` 不会被计算,即使它和 `f(x)` 的结果是相反的。
**值得注意的是:**`&&``||` 运算符遵循短路规则,这意味着,假如存在 `f(x) || g(y)` 的表达式,如果 `f(x)``true``g(y)` 不会被计算,即使它和 `f(x)` 的结果是相反的。假如存在`f(x) && g(y)` 的表达式,如果 `f(x)``false``g(y)` 不会被计算。

### 2. 整型

整型是 Solidity 中的整数,最常用的包括:

```solidity
// 整型
int public _int = -1; // 整数,包括负数
uint public _uint = 1; // 正整数
uint256 public _number = 20220330; // 256位正整数
// 整型
int public _int = -1; // 整数,包括负数
uint public _uint = 1; // 正整数
uint256 public _number = 20220330; // 256位正整数
```

常用的整型运算符包括:

- 比较运算符(返回布尔值): `<=``<``==``!=``>=``>`
- 比较运算符(返回布尔值): `<=``<``==``!=``>=``>`
- 算数运算符: `+``-``*``/``%`(取余),`**`(幂)

```solidity
// 整数运算
uint256 public _number1 = _number + 1; // +,-,*,/
uint256 public _number2 = 2**2; // 指数
uint256 public _number3 = 7 % 2; // 取余数
bool public _numberbool = _number2 > _number3; // 比大小
// 整数运算
uint256 public _number1 = _number + 1; // +,-,*,/
uint256 public _number2 = 2**2; // 指数
uint256 public _number3 = 7 % 2; // 取余数
bool public _numberbool = _number2 > _number3; // 比大小
```

大家可以运行一下代码,看看这 4 个变量分别是多少。

### 3. 地址类型

地址类型(address)有两类:

- 普通地址(address): 存储一个 20 字节的值(以太坊地址的大小)。
Expand All @@ -91,11 +96,11 @@ tags:
我们会在之后的章节更加详细地介绍 payable address。

```solidity
// 地址
address public _address = 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71;
address payable public _address1 = payable(_address); // payable address,可以转账、查余额
// 地址类型的成员
uint256 public balance = _address1.balance; // balance of address
// 地址
address public _address = 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71;
address payable public _address1 = payable(_address); // payable address,可以转账、查余额
// 地址类型的成员
uint256 public balance = _address1.balance; // balance of address
```

### 4. 定长字节数组
Expand All @@ -106,37 +111,45 @@ tags:
- 不定长字节数组: 属于引用类型(之后的章节介绍),数组长度在声明之后可以改变,包括 `bytes` 等。

```solidity
// 固定长度的字节数组
bytes32 public _byte32 = "MiniSolidity";
bytes1 public _byte = _byte32[0];
// 固定长度的字节数组
bytes32 public _byte32 = "MiniSolidity";
bytes1 public _byte = _byte32[0];
```

在上述代码中,`MiniSolidity` 变量以字节的方式存储进变量 `_byte32`。如果把它转换成 `16 进制`,就是:`0x4d696e69536f6c69646974790000000000000000000000000000000000000000`

`_byte` 变量的值为 `_byte32` 的第一个字节,即 `0x4d`

### 5. 枚举 enum

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

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

枚举可以显式地和 `uint` 相互转换,并会检查转换的正整数是否在枚举的长度内,否则会报错:

```solidity
// enum可以和uint显式的转换
function enumToUint() external view returns(uint){
return uint(action);
}
// enum可以和uint显式的转换
function enumToUint() external view returns(uint){
return uint(action);
}
```

`enum` 是一个比较冷门的变量,几乎没什么人用。

## 在 Remix 上运行

- 部署合约后可以查看每个类型的变量的数值:

![2-1.png](./img/2-1.png)

- `enum``uint` 转换的示例:

![2-2.png](./img/2-2.png)
![2-3.png](./img/2-3.png)

Expand Down
2 changes: 1 addition & 1 deletion 03_Function/Function.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ contract FunctionTypes{
new_number = number + 1;
}

// internal: 内部
// internal: 内部函数
function minus() internal {
number = number - 1;
}
Expand Down
85 changes: 48 additions & 37 deletions 03_Function/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tags:

# WTF Solidity极简入门: 3. 函数

我最近在重新学solidity,巩固一下细节,也写一个“WTF Solidity极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。
我最近在重新学Solidity,巩固一下细节,也写一个“WTF Solidity极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。

推特:[@0xAA_Science](https://twitter.com/0xAA_Science)

Expand All @@ -25,7 +25,7 @@ Solidity语言的函数非常灵活,可以进行各种复杂操作。在本教
我们先看一下 Solidity 中函数的形式:

```solidity
function <function name>(<parameter types>) {internal|external|public|private} [pure|view|payable] [returns (<return types>)]
function <function name>(<parameter types>) {internal|external|public|private} [pure|view|payable] [returns (<return types>)]
```

看着有一些复杂,让我们从前往后逐个解释(方括号中的是可写可不
Expand Down Expand Up @@ -53,6 +53,7 @@ Solidity语言的函数非常灵活,可以进行各种复杂操作。在本教
6. `[returns ()]`:函数返回的变量类型和名称。

## 到底什么是 `Pure``View`

刚开始学习 `solidity` 时,`pure``view` 关键字可能令人费解,因为其他编程语言中没有类似的关键字。`solidity` 引入这两个关键字主要是因为 以太坊交易需要支付气费(gas fee)。合约的状态变量存储在链上,gas fee 很贵,如果计算不改变链上状态,就可以不用付 `gas`。包含 `pure``view` 关键字的函数是不改写链上状态的,因此用户直接调用它们是不需要付 gas 的(注意,合约中非 `pure`/`view` 函数调用 `pure`/`view` 函数时需要付gas)。

在以太坊中,以下语句被视为修改链上状态:
Expand All @@ -68,7 +69,6 @@ Solidity语言的函数非常灵活,可以进行各种复杂操作。在本教

为了帮助大家理解,我画了一个马里奥插图。在这幅插图中,我将合约中的状态变量(存储在链上)比作碧琪公主,三种不同的角色代表不同的关键字。


![WTF is pure and view in solidity?](https://images.mirror-media.xyz/publication-images/1B9kHsTYnDY_QURSWMmPb.png?height=1028&width=1758)

- `pure`,中文意思是“纯”,这里可以理解为”纯打酱油的”。`pure` 函数既不能读取也不能写入链上的状态变量。就像小怪一样,看不到也摸不到碧琪公主。
Expand All @@ -78,77 +78,88 @@ Solidity语言的函数非常灵活,可以进行各种复杂操作。在本教
-`pure``view` 的函数既可以读取也可以写入状态变量。类似马里奥里的 `boss`,可以对碧琪公主为所欲为🐶。

## 代码

### 1. pure 和 view

我们在合约里定义一个状态变量 `number`,初始化为 5。

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract FunctionTypes{
uint256 public number = 5;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract FunctionTypes{
uint256 public number = 5;
}
```

定义一个 `add()` 函数,每次调用会让 `number` 增加 1。

```solidity
// 默认
function add() external{
number = number + 1;
}
// 默认function
function add() external{
number = number + 1;
}
```

如果 `add()` 函数被标记为 `pure`,比如 `function add() external pure`,就会报错。因为 `pure` 是不配读取合约里的状态变量的,更不配改写。那 `pure` 函数能做些什么?举个例子,你可以给函数传递一个参数 `_number`,然后让他返回 `_number + 1`,这个操作不会读取或写入状态变量。

```solidity
// pure:
function addPure(uint256 _number) external pure returns(uint256 new_number){
new_number = _number + 1;
}
// pure: 纯纯牛马
function addPure(uint256 _number) external pure returns(uint256 new_number){
new_number = _number + 1;
}
```

![3-3.png](./img/3-3.png)

如果 `add()` 函数被标记为 `view`,比如 `function add() external view`,也会报错。因为 `view` 能读取,但不能够改写状态变量。我们可以稍微改写下函数,读取但是不改写 `number`,返回一个新的变量。

```solidity
// view: 看客
function addView() external view returns(uint256 new_number) {
new_number = number + 1;
}
// view: 看客
function addView() external view returns(uint256 new_number) {
new_number = number + 1;
}
```

![3-4.png](./img/3-4.png)

### 2. internal v.s. external

```solidity
// internal: 内部函数
function minus() internal {
number = number - 1;
}
// 合约内的函数可以调用内部函数
function minusCall() external {
minus();
}
// internal: 内部函数
function minus() internal {
number = number - 1;
}
// 合约内的函数可以调用内部函数
function minusCall() external {
minus();
}
```

我们定义一个 `internal``minus()` 函数,每次调用使得 `number` 变量减少 1。由于 `internal` 函数只能由合约内部调用,我们必须再定义一个 `external``minusCall()` 函数,通过它间接调用内部的 `minus()` 函数。

![3-1.png](./img/3-1.png)

### 3. payable

```solidity
// payable: 递钱,能给合约支付eth的函数
function minusPayable() external payable returns(uint256 balance) {
minus();
balance = address(this).balance;
}
// payable: 递钱,能给合约支付eth的函数
function minusPayable() external payable returns(uint256 balance) {
minus();
balance = address(this).balance;
}
```

我们定义一个 `external payable``minusPayable()` 函数,间接的调用 `minus()`,并且返回合约里的 ETH 余额(`this` 关键字可以让我们引用合约地址)。我们可以在调用 `minusPayable()` 时往合约里转入1个 ETH。
我们定义一个 `external payable``minusPayable()` 函数,间接的调用 `minus()`,并且返回合约里的 ETH 余额(`this` 关键字可以让我们引用合约地址。我们可以在调用 `minusPayable()` 时往合约里转入1个 ETH。

![](https://images.mirror-media.xyz/publication-images/ETDPN8myq7jFfAL8CUAFt.png?height=148&width=588)
![mirror-image-1](https://images.mirror-media.xyz/publication-images/ETDPN8myq7jFfAL8CUAFt.png?height=148&width=588)

我们可以在返回的信息中看到,合约的余额变为 1 ETH。

![](https://images.mirror-media.xyz/publication-images/nGZ2pz0MvzgXuKrENJPYf.png?height=128&width=1130)
![mirror-image-2](https://images.mirror-media.xyz/publication-images/nGZ2pz0MvzgXuKrENJPYf.png?height=128&width=1130)

![3-2.png](./img/3-2.png)

## 总结

在这一讲,我们介绍了 `Solidity` 中的函数。`pure``view` 关键字比较难理解,在其他语言中没出现过:`view` 函数可以读取状态变量,但不能改写;`pure` 函数既不能读取也不能改写状态变量。
Loading

0 comments on commit e0d6430

Please sign in to comment.