diff --git a/README.md b/README.md
index 2cf57d1..469b365 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,14 @@
# Solidity 高级程序设计
-**前置说明**:
+❌❌❌
+注意:
-这个教程的目标读者是那些已经熟悉 Solidity 语言基本用法的人,他们可能已经编写过一些简单的智能合约,并对 Solidity 的核心概念和语法有一定的了解。如果您已经掌握了 Solidity 的基本用法,这个教程可以帮助您填补一些知识的空白,并深入学习更高级的概念和技术。
+这这个教程的目标读者是已经熟悉 Solidity 语言基本用法的人。如果您已经掌握了 Solidity 的基本用法,这个教程可以帮助您填补知识的空白,并深入学习更高级的概念和技术。
-对于更好地阅读和理解这个教程,确实需要具备一定的 Solidity 基础知识,并且最好具备其他语言的生产级项目编码水平。
-
-对于完全零基础的 Solidity 小白来说,这个教程可能并不适合作为他们初次接触。
-
-如果您是一个初学者,我建议您首先学习 Solidity 的基础知识。您可以通过阅读 Solidity 的官方文档和教程来入门,掌握 Solidity 的基本语法、数据类型、控制流程等。一旦您对 Solidity 有了一定的了解,您可以尝试编写简单的智能合约,以加深对 Solidity 的理解。
+对于完全零基础的 Solidity 小白来说,这个教程可能并不适合作为他们初次接触。 如果您是一个初学者,我建议您首先学习 Solidity 的基础知识。您可以通过阅读 Solidity 的官方文档和教程来入门,掌握 Solidity 的基本语法、数据类型、控制流程等。
在学习 Solidity 的过程中,如果您遇到任何问题,都可以随时向我提问。我将尽力帮助您理解和解决问题。
-
-
-❌❌❌ 注意:
-
-这个前置条件非常重要,对于没有编程基础的人来说,阅读这个教程可能会非常困难。如果您没有掌握 Solidity 的基本用法或其他编程语言的经验,确实建议您先学习编程的基础知识和其他语言,然后再尝试深入学习 Solidity。
-
-如果您在学习 Solidity 的过程中遇到困难,可以随时向我提问。我会尽力为您提供帮助和解答。同时,使用搜索引擎和参考其他教程和资源也是一个很好的学习策略,因为这样可以获取更多的知识和解决问题的方法。
+同时,使用搜索引擎和参考其他教程和资源也是一个很好的学习策略,因为这样可以获取更多的知识和解决问题的方法。
另外,关于Solidity学习资源的地址,一下是一些常用的学习资源,供大家参考:
- [Solidity 官方文档](https://blog.soliditylang.org/)
@@ -60,14 +51,8 @@
- 实体书籍:方便有读书习惯的人阅读。
-如果你喜欢这个项目,请给它点一个[](https://github.com/你的GitHub用户名/你的项目仓库名)(GitHub上的点赞按钮)。
-
-## 贡献
-
-我们欢迎并鼓励您对所有文档、源代码以及相关视频的开放与免费访问。此外,我们还提供了配套的PDF文件,同样也是免费提供的。我们欢迎您在GitHub仓库上提交您的改动,以帮助我们不断优化内容。如果您对参与教程的修改和改进感兴趣,修改GitHub源文件是最简单的方式。
-
+如果你喜欢这个项目,请给它点一个[](https://github.com/anbang/professional-solidity)(GitHub上的点赞按钮)。
-## 在线阅读
- **文字版在线阅读**:
- 墙内版: 阿西河网站
@@ -76,10 +61,42 @@
- [在线视频观看: Youtube](https://www.youtube.com/watch?v=ao5nkAgx7kU&list=PLdXBX6Eqe4Net43OWIZychHW0n6CX_8Ih)
- [在线视频观看: Bilibili](https://www.bilibili.com/video/BV1HR4y197Ag)
-## TODO
-下面是给这本书做的 TODO List
+## 贡献
+
+我们欢迎并鼓励您对所有文档、源代码以及相关视频的开放与免费访问。此外,我们还提供了配套的PDF文件,同样也是免费提供的。我们欢迎您在GitHub仓库上提交您的改动,以帮助我们不断优化内容。如果您对参与教程的修改和改进感兴趣,修改GitHub源文件是最简单的方式。
+
+## 本地运行文档
+
+克隆本仓库到你的电脑
+
+```
+git clone git@github.com:anbang/professional-solidity.git
+```
+
+**安装 Sphinx**:
+
+```
+yum -y install git make python3 python3-pip
+pip3 install sphinx
+pip3 install sphinx-autobuild
+pip3 install sphinx_rtd_theme
+pip3 install recommonmark
+pip3 install sphinx_markdown_tables
+```
+
+**本地运行**:根目录执行如下命令
+
+```
+# 第一种
+sphinx-autobuild docs build/html
+
+# 第二种
+./start.sh
+```
+
+## TODO List
1. ✅ 最迟不晚于 2022 年 11 月提供前 3 章的内容用来做市场测试,如果有必要的话,提供配套的视频版
2. ✅ 最迟不晚于 2023 年 1 月提供 V0.0.1 版本,并在 V0.0.1 版本完成初步架构
3. ❌ 最迟不晚于 2023 年 3 月提供 V0.0.2 版本,并在 V0.0.2 开始提供完整的 PDF 版电子书籍
@@ -88,9 +105,9 @@
6. ❌ 如果一切顺利的话,联系出版社给印刷出来。
7. ❌ 重新录制完整的视频配套教程
-7 个步骤,目前完成了 2 个。一切都按照计划进行中。
+目前已完成 2 个步骤,进度符合计划。
-最开始写了前面 3 章内容,并在 2022 年 10 月下旬录制了配套视频教程,并分享在 Bilibili 上,有赞的有吐槽的;但是后台数据上来看这类资料在 Solidity 这个垂直语言内还是很受欢迎的。目前在 B 站搜索常见的 Solidity 关键字,我分享的视频教程几乎都是系统默认推荐的第 1 名。总播放量也在 12 月份进了前 10。并在 2022 年 12 月下旬完成了 V0.0.1 版本内容,初步完成了这本书的架构。
+**里程碑回顾-2022.12.29**:编写了前三章的内容,并于2022年10月下旬录制了配套视频教程,并在Bilibili上分享。视频教程收到了赞扬和批评,但根据后台数据显示,在Solidity这个特定领域,这类资料仍然非常受欢迎。目前在Bilibili上搜索与Solidity相关的关键字,我分享的视频教程几乎都是系统默认推荐的第一名。总播放量也在12月份进入前十名。在2022年12月下旬,完成了V0.0.1版本内容,并初步完成了本书的架构。
## 目录
@@ -295,35 +312,17 @@
* [3️⃣ 文件结构分享](./docs/forever/22.styleguide.md#3%EF%B8%8F⃣-文件结构分享)
* [4️⃣ 命名约定](./docs/forever/22.styleguide.md#4%EF%B8%8F⃣-命名约定)
* [5️⃣ 更多内容](./docs/forever/22.styleguide.md#5%EF%B8%8F⃣-更多内容)
-
-
-本来是做了 24 章的内容,但是为了以后方便印刷成纸质,所以删除了**真实案例分析**和**合约常见错误分析**这两个含有大量代码演示的章节。(比如案例分析里,光 uniswap V2/V3 和 Compound 这 3 个合约,每个印出来都是几十页的内容,太浪费篇幅了,以后单独放出来)
-
-## 本地运行文档
-
-克隆本仓库到你的电脑
-
-```
-git clone git@github.com:anbang/professional-solidity.git
-```
-**安装 Sphinx**:
-
-```
-yum -y install git make python3 python3-pip
-pip3 install sphinx
-pip3 install sphinx-autobuild
-pip3 install sphinx_rtd_theme
-pip3 install recommonmark
-pip3 install sphinx_markdown_tables
-```
+
+
+
+ 您的贡献将帮助我们成长
+
+
+
+
+
-**本地运行**:根目录执行如下命令
+本来是做了 24 章的内容,但是为了以后方便印刷成纸质,所以删除了**真实案例分析**和**合约常见错误分析**这两个含有大量代码演示的章节。(比如案例分析里,光 uniswap V2/V3 和 Compound 这 3 个合约,每个印出来都是几十页的内容,太浪费篇幅了,以后单独放出来)
-```
-# 第一种
-sphinx-autobuild docs build/html
-# 第二种
-./start.sh
-```
diff --git a/docs/source/01.hello.md b/docs/source/01.hello.md
index 3d8464c..94f3369 100644
--- a/docs/source/01.hello.md
+++ b/docs/source/01.hello.md
@@ -444,36 +444,45 @@ contract MyContract is SomeInterface {
### 3.contract 关键字
-第 3 行的 `contract Hello {}` 是合约的基本结构;其中 `contract` 声明了当前代码块内是一个完整的合约。而 `Hello` 是当前合约的名字,合约名称是必须的,首字母一般采用大写字母开头。
+第 3 行的 `contract Hello {}` 是合约的基本结构;其中 `contract` 声明了当前代码块内是一个完整的合约。而 `Hello` 是当前合约的名称,合约名称是必须的,首字母一般采用首字母大写的驼峰命名法。
-`contract` 代表特殊的意义,这种有特殊意义的词,在编程界里一般被称为 `保留关键字`;保留关键字是现在或者将来被用到的特殊代指,都有固定意义,所以保留关键字不能作为变量名和函数名字。
+`contract` 是具有特殊意义的保留关键字.保留关键字在编程界中知道特定的概念,具有固定的含义.因此保留关键字不能作为变量名和函数名使用。
- **总结:**
- 1. contract 基本结构是 `contract ContractName {}`
- 2. Solidity 合约中,合约的名字是必须的。
- 3. 合约的名称,一般约定为 大驼峰命名方式
- 4. contract 是保留关键字
- 5. 保留关键字不能作为变量名和函数名
+ 1. 合约 基本结构是 `contract ContractName {}`。
+ 2. Solidity合约中,合约的名称是必须的。
+ 3. 合约的名称通常采用大驼峰命法。
+ 4. contract 是保留关键字。
+ 5. 保留关键字不能作为变量名和函数名。
- **扩展:**
- 1. 合约的编写规范,参照 [合约编码规范](/forever/903.styleguide.md)
- 2. 更多保留关键字,参照 [变量名命名规则](/source/03.variable.html#id11) 详细阅读。
+ 1. 可参考 [合约编码规范](/forever/903.styleguide.md)了解编码规范
+ 2. 了解更多保留关键字,请参考[变量名命名规则](/source/03.variable.html#id11)。
-注:一份源文件可以包含多个版本声明、多个导入声明和**多个合约声明**。
+请注意:一个源文件可以包含多个版本声明、多个导入声明和**多个合约声明**。
#### ⓵ 变量
-合约内的 `message` 叫做状态变量,状态变量是永久地存储在合约存储中的值。关于变量的更多信息,会在后续 [变量](/source/03.variable.html) 那一章详细介绍
+在合约内部,`contract` 状态变量是永久地存储在合约存储中的值。关于变量的更多信息,会在后续 [变量](/source/03.variable.html) 章节中详细介绍
+状态变量是合约中用于存储和跟踪数据的重要组成部分。它们的值可以在合约的整个生命周期内持久存在,直到被修改或删除。
+
+如果您对变量有更多的疑问或想要深入了解,请继续阅读后续的 变量 章节。那里将提供更详细的信息和解释。
#### ⓶ 函数
-函数是代码的可执行单元,是一组逻辑的集合。关于变量的更多信息,会在后续 [函数](/source/04.function.html) 那一章详细介绍
+函数是代码的可执行单元,它们由一组逻辑语句组成。关于变量的更多信息将在后续的 [函数](/source/04.function.html) 章节中详细介绍。
+
+函数在 Solidity 合约中起着重要的作用,用于执行特定的任务和操作。通过函数,您可以定义代码逻辑、操作状态变量、处理输入参数等。
+
+如果您对函数有更多的疑问或想要深入了解,请继续阅读后续的 函数 章节。那里将提供更详细的信息和解释。
#### ⓷ this 关键字
-Solidity 中 `this` 代表合约对象本身;
+Solidity 中, `this`关键字代表合约对象本身
+
+一下是关于`this`的两个常见用法:
-- 可以通过 `address(this)` 获取合约地址。
-- 可以通过 `this.fnName` 获取 external 函数
+- 可以通过 `address(this)` 获取合约地址。 这在某些情况下会很有用,例如需要将合约地址传递给其他合约或外部调用者。
+- 可以通过 `this.fnName` 获取 external 函数。
```
// SPDX-License-Identifier: MIT
@@ -490,9 +499,16 @@ contract Demo {
}
```
+在上面的示例中,`contractAddr`函数放回了当前合约的地址,而`textExternal`函数通过`this.contractAds()`调用了`contractAds`函数并返回合约地址。
+
#### ⓸ 合约地址/合约创建者地/合约调用者地址
-这三个地址概念一定要完全理解。
+在 Solidity 中,有三个地址的概念:
+- `address(this)`:合约地址 表示合约在区块链上的唯一标识
+- `msg.sender`:合约调用者地址 表示当前合约的调用者地址
+- `tx.origin`:合约创建者地址 表示当前合约的创建者地址
+
+在下面的示例合约中,我们可以看到对这三个地址概念的应用:
```
// SPDX-License-Identifier: MIT
@@ -503,29 +519,35 @@ contract Demo {
address public owner;
constructor() {
- // 可以用在 constructor 内获取当前合约地址
- owner = address(this);
-
- // 不可以在构造函数内调用函数,因为此时合约还没有完成构建好。
- // this.caller(); 相当于从外部调用 caller 方法
- // owner = this.caller();
+ owner = address(this); // 在构造函数中获取当前合约地址
}
function caller() external view returns (address) {
- return this.contractAds(); // 内部调用 external 可见性的函数
+ return this.contractAds(); // 在合约内部调用 external 可见性的函数
}
function contractAds() external view returns (address) {
- return address(this);
+ return address(this); // 返回当前合约的地址
}
}
```
+在上面的示例中,我们通过`address(this)`获取了当前合约的地址,并将其赋值给了`owner`变量。在`caller`函数中,我们通过`this.contractAds()`调用了`contractAds`函数并返回合约地址。
+
+请注意:在构造函数中调用函数是不推荐的做法,因为在构造函数执行期间,合约可能还没有完全构建完毕.所以,构造函数内部调用函数时需要特别小心。
+
+
#### ⓹ 合约属性:type 关键字
-- `type(C).name`:获得合约名
-- `type(C).creationCode`:获得包含创建合约字节码的内存字节数组。它可以在内联汇编中构建自定义创建例程,尤其是使用 create2 操作码。 不能在合约本身或派生的合约访问此属性。 因为会引起循环引用。
-- `type(C).runtimeCode`:获得合约的运行时字节码的内存字节数组。这是通常由 C 的构造函数部署的代码。 如果 C 有一个使用内联汇编的构造函数,那么可能与实际部署的字节码不同。 还要注意库在部署时修改其运行时字节码以防范定期调用(guard against regular calls)。 与 .creationCode 有相同的限制,不能在合约本身或派生的合约访问此属性。 因为会引起循环引用。
+使用 `type` 关键字可以获取合约的属性,包括合约名、创建字节码和运行时字节码。
+
+以下是关于`type`关键字的属性的详细说明:
+
+- `type(C).name`:获取合约名。在示例合约中,使用`type(C).name`返回合约`Hello`的名称
+- `type(C).creationCode`:获取包含创建合约字节码的内存字节数组。该属性主要是用于内联汇编,在构建自定义创建过程时特别有用。需要注意的是,合约本身或派生合约无法访问此属性,因为可能导致循环利用。
+- `type(C).runtimeCode`:获取合约的运行时字节码的内存字节数组。这是通常有合约的构造函数部署的代码。如果合约的构造函数使用了内联汇编,则实际部署的字节码可能与此属性返回的字节码不同。还需要注意的是,库合约在部署时会修改其运行时字节码以防范定期调用。合约本身或派生合约无法访问此属性。
+
+在下面的示例合约中,我们演示了如何使用:`type`关键字获取合约的属性:
```
// SPDX-License-Identifier: MIT
@@ -537,57 +559,71 @@ contract Hello {
contract Demo {
function name() external pure returns (string memory) {
- return type(Hello).name;
+ return type(Hello).name; // 获取合约名
}
function creationCode() external pure returns (bytes memory) {
- return type(Hello).creationCode;
+ return type(Hello).creationCode; // 获取创建字节码
}
function runtimeCode() external pure returns (bytes memory) {
- return type(Hello).runtimeCode;
+ return type(Hello).runtimeCode; // 获取运行时字节码
}
}
```
-除了上面介绍的版权声明,版本限制,contract 外,合约文件还包括 `import`, `interface`,`library`,一起展开介绍下
+除了上面介绍的版权声明,版本限制和`contract`关键字外,合约文件还包括 `import`, `interface`,`library`等内容。这些内容在后续章节中将详细展开介绍。
### 4.import 导入声明
-功能:从其他文件内倒入需要的变量或者函数。
+导入声明的功能是从其他文件中导入所需的变量和函数。
#### ⓵ 导入方式
-既可以导入**本地文件**,也可以导入 **url**(网络上的 ipfs,http 或者 git 文件)
+可以导入**本地文件**,也可以导入 **url**(如 IPFS、HTTP 或 Git 文件)。
-1. **导入所有的全局标志** `import "filename";` 到当前全局范围
- 1. 导入本地文件:`import "./ERC20.sol";`,其中`./`表示当前目录,查找路径参考
+1. **导入所有的全局标志** `import "filename";` 将所有全局标识符导入到当前的全局范围内。
+ 1. 导入本地文件:`import "./ERC20.sol";`,其中`./`表示当前目录,具体的查找路径请参考具体规范
2. 导入网络文件:`import "https://github.com/aaa/.../tools.sol";`
3. 导入本地 NPM 库:
1. `$ npm install @openzeppelin/contracts`
2. `import "@openzeppelin/contracts/token/ERC721/ERC721.sol";`
-2. **导入所有的全局标志,并创建新的全局符号**
+2. **导入所有的全局标志并创建新的全局符号**
1. 方式一: `import * as symbolName from "filename";`
2. 方式二: `import "filename" as symbolName;`
-3. 按需导入,按需修改名称
+3. 按需导入并修改名称
1. `import {symbol1 as aliasName, symbol2} from "filename";`
-不推荐导入变量标示名到当前全局范围的方式,因为不可控,容易污染当前的命名空间。如果全局导入,推荐使用 `import "filename" as symbolName;`
+不推荐将变量标识符导入到当前全局范围,因为这样做会导致命名空间的污染和不可控性。如果要全局导入,建议使用 `import "filename" as symbolName;`的方式。
-注:一份源文件可以包含多个版本声明、多**个导入声明**和多个合约声明。
+注意:一份源文件可以包含多个版本声明、多**个导入声明**和多个合约声明。
#### ⓶ 导入时候的本地路径
-上文中的 filename 总是会按路径来处理,以 `/` 作为目录分割符、以 `.` 标示当前目录、以 `..` 表示父目录。 当 `.` 或 `..` 后面跟随的字符是 `/` 时,它们才能被当做当前目录或父目录。 只有路径以当前目录 `.` 或父目录 `..` 开头时,才能被视为相对路径。
+在Solidity中,导入语句中`filename`总是按照路径处理,以`/`作为目录分隔符。这意味着可以使用相对路径或绝对路径来指定要导入文件的位置。
-用 `import "./x.sol" as x;` 语句导入当前源文件同目录下的文件 `x.sol` 。 如果用`import "x.sol" as x;` 代替,可能会引入不同的文件(在全局 `include directory` 中)。
+当使用相对路径时,可以使用`.`来表示当前目录,`..`表示父目录。只有路径以`.`或`..`开头,并且后面跟随的字符是`/`,才能被解析为当前目录或父目录。
-最终导入哪个文件取决于编译器(见下文)到底是怎样解析路径的。 通常,目录层次不必严格映射到本地文件系统, 它也可以映射到能通过诸如 ipfs,http 或者 git 发现的资源。
+例如,假设有以下文件结构:
+```
+├── contracts
+│ ├── main.sol
+│ └── utils.sol
+└── README.md
+```
+
+在`main.sol`,要导入同一目录下的`utils.sol`文件,可以使用相对路径`import "./utils.sol" as utils;`。这会告诉编译器在当前目录中查找`utils.sol`文件。
+
+如果要导入`contracts`目录下的`utils.sol`文件,可以使用相对路径`import "../contracts/utils.sol" as utils;`。这里的`..`表示回到父目录,然后在进入`contracts`。
+
+如果要使用绝对路径来导入文件,例如`import "/contracts/utils.sol" as utils;`,那么编译器将会在全局的根目录中查找`contracts`目录。这个全局的目录可以根据具体的Solidity编译器和设置而定。
+
+总体来说,根据路径的不同,编译器会解析不同的文件。因此,在编写导入语句时,需要根据文件的实际位置,选择正确的路径表示 方式,以确保成功导入所需的文件。
### 5.interface: 接口
#### ⓵ 接口使用案例
-在下面的例子中,定义了 cat 合约以及 dog 合约。他们都有 `eat` 方法.以此他们都可以被上面的 `animalEat` 接口所接收。
+在下面的例子中,定义了 Cat 合约以及 Dog 合约。它们都有 `eat` 方法.因此它们都可以被上面的 `AnimalEat` 接口所接收。
```
// SPDX-License-Identifier: MIT
@@ -633,9 +669,9 @@ contract Animal {
#### ⓶ `type(I).interfaceId`
-返回接口`I` 的 `bytes4` 类型的接口 ID,接口 ID 参考: [EIP-165](https://learnblockchain.cn/docs/eips/eip-165.html) 定义的, 接口 ID 被定义为 XOR (异或) 接口内所有的函数的函数选择器(除继承的函数。
+通过`type(I).interfaceId`可以返回接口`I` 的 `bytes4` 类型的接口ID,接口 ID 参考: [EIP-165](https://learnblockchain.cn/docs/eips/eip-165.html) , 接口ID 被定义为接口内所有函数的函数选择器的 XOR(异或)结果(除了继承的函数)。
-上面的代码种,可以增加如下的函数来查看 `interfaceId`;
+上面的代码种,可以增加以下的函数来查看 `interfaceId`;
```
contract Animal {
@@ -646,11 +682,13 @@ contract Animal {
}
```
-更多内容在 [interface:接口](/source/13.interface.html) 那一章详细介绍。
+更多关于接口的内容可以在 [interface:接口](/source/13.interface.html) 这一章节中详细介绍。
### 6.library:库合约
-库与合约类似,但它的目的是在一个指定的地址,且仅部署一次,然后通过 EVM 的特性来复用代码。
+库合约类似与普通合约,但是它们不能被单独部署,也不能被继承。库合约可以被其他合约使用,库合约中的函数可以被其他合约调用。
+
+以下是一个库合约的示例:
```
library Set {
@@ -659,14 +697,18 @@ library Set {
}
}
```
+其他合约可以通过直接调用库合约的名称来调用起函数,例如:`Set.test()`。
-其他合约调用库文件的内容直接通过库文件名.方法名例如:`Set.test()`。
+库合约的主要特点包括:
+- 库合约只能包含库函数,不能包含状态变量。
+- 库合约的函数可以通过访问库中定义的结构体和存储变量。
+- 库函数在被调用时,会将其东盎用上下文的数据作为参数传递,而不需要显式指定引用。
-更多内容在 [Library:库](/source/14.library.html) 那一章详细介绍。
+库合约的主要优势是可以在多个合约中共享和重用代码逻辑,减少重复开发和部署的成本。
-## 5️⃣ 全局的以太币单位
+更多内容在 [Library:库](/source/14.library.html)章节有详细介绍。
-现实生活中经常会听说,提现 1.5 个以太币,或者某笔交易手续费花了 0.02 个以太坊等。这些带有小数点的数字是日常交流使用的。但是在合约内,却没有这种小数概念的货币金额。比如 1 个 ETH 的金额是 `10**18 wei`。
+## 5️⃣ 全局的以太币单位
### 本节配套视频
@@ -675,13 +717,14 @@ library Set {
### 1.基础单位
-为了方便合约开发者操作,也提供如下这种便捷的换算方式。
-
-以太币单位之间的换算就是在数字后边加上 `wei`、 `gwei`、 `ether` 来实现的,如果后面没有单位,缺省为 `wei`。例如 `1 ether == 1e18` 的逻辑判断值为 true。
+在以太坊合约中没有直接支持小数点的货币金额概念,而是使用基本单位来表示金额。为了方便,以太坊提供了一种编写的换算方式,可以在数值后面加上`wei`、`gwei`、`ether`等单位来表示不同的金额。
- `1 ether = 1 * 10^18 wei`
- `1 ether = 1 * 10^9 gwei`
+例如,`1 ether == 1e18`。
+
+下面是一个示例合约,演示了基本单位的使用方法。
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
@@ -696,6 +739,10 @@ contract Demo {
}
```
+在上述示例中,`test` 函数返回了三个布尔值,分别表示 `1 wei`、`1 gwei`、`1 ether` 是否等于 `1`。
+
+通过这种方式,合约开发者可以方便的进行金额的计算,而不需要关心具体的单位。请注意使用适当的Solidity版本进行编译。
+
### 2.变量使用以太币单位
**注意: 这些后缀不能直接用在变量后边**。如果想用以太币单位来计算输入参数,你可以使用乘法来转换: `amountEth * 1 ether`
@@ -728,17 +775,15 @@ contract Demo {
## 6️⃣ 接收 ETH
-三个关键字
-
-- payable
- - 使用 payable 标记的**函数**可以用于发送和接收 Eth。
- - 使用 payable 标记的 **地址变量**,允许发送和接收 Eth。
-- fallback
- - 一个合约可以最多有一个回退函数。
-- receive
- - 一个合约最多有一个 `receive` 函数
+在以太坊智能合约中有几种方式是可以接受以太币(ETH).
+- payable函数:
+ - 使用 payable 标记的**函数**可以用于发送和接收 Eth。当其他用户调用这个函数时,他们可以在交易中附带一定数量的以太币。
+- fallback函数:
+ - fallback 函数是一种特殊的函数,当合约接收到以太币时,会自动调用 fallback 函数。
+- receive函数:
+ - 个合约最多只能有一个 receive 函数。该函数没有参数,且没有函数名。当合约接收到以太币时,会自动调用该函数。您可以在 receive 函数中处理接收到的以太币
-fallback 和 receive 不是普通函数,而是新的函数类型,有特别的含义,它们前面不需要加 `function` 这个关键字。加上 `function` 之后,它们就变成了一般的函数,只能按一般函数来去调用。同时 `receive` 和 `fallback` 需要注意 gas 消耗。
+fallback 和 receive 是特殊类型的函数,不需要在签名加 `function` 这个关键字,他们具有特殊的含义和行为。相反,如果在它们前面加上 `function` 关键字,它们将被视为普通的函数,只能按普通函数的方式调用。同时 `receive` 和 `fallback` 需要注意 gas 消耗。
本节介绍的是合约如何接收 ETH,至于合约如何发送 ETH,请阅读 [两种形式的地址](/source/02.type-of-data.html#id24) 这一节。
@@ -758,23 +803,25 @@ fallback 和 receive 不是普通函数,而是新的函数类型,有特别
pragma solidity ^0.8.17;
contract Payable {
- // payable 标记函数
+ // 使用 payable 标记的函数可以接受以太币
function deposit1() external payable {}
function deposit2() external {}
- // payable 标记地址
+ // 使用 payable 标记的地址变量允许发送和接受以太币
function withdraw() external {
payable(msg.sender).transfer(address(this).balance);
}
- // 通过 balance 属性,来查看余额。
+ // 通过 balance 属性,来查看合约的余额。
function getBalance() external view returns (uint256) {
return address(this).balance;
}
}
```
+
+
可以使用 deposit 存款,但是如果使用 calldata 转账,则会失败,报错 _In order to receive Ether transfer the contract should have either 'receive' or payable 'fallback' function_
### 2.fallback