网站营销是什么意思,茶叶网站开发目的和意义,wordpress下拉插件,网站建设与管理可以专升本吗一.区块链的回顾
1.区块链
区块链实质上是一个去中心化、分布式的可进行交易的数据库或账本
特征:
去中心化#xff1a;简单来说#xff0c;在网络上一个或多个服务器瘫痪的情况下#xff0c;应用或服务仍然能够持续地运行#xff0c;这就是去中心化。服务和应用部署在…一.区块链的回顾
1.区块链
区块链实质上是一个去中心化、分布式的可进行交易的数据库或账本
特征:
去中心化简单来说在网络上一个或多个服务器瘫痪的情况下应用或服务仍然能够持续地运行这就是去中心化。服务和应用部署在网络上后尽管每个服务器都有一份数据和执行程序的副本但是没有任何一个服务器能够绝对控制数据和程序的执行过程。 分布式网络上的每个服务器或节点都互相连接在一起服务器之间是多对多连接而不是一对一或一对多连接。数据库指的是存储持久化数据、用户能够及时从任何地点进行访问的地方。数据库的基本功能是数据存储和检索同时也提供了一些管理功能以方便高效地管理数据如数据导入和导出数据备份和恢复。 账本这是一个会计专业术语。你也可以认为它是一个专门存储和检索数据的地方。账本对银行业而言很有用处。例如Tom在他的银行账户上存入了100美元对银行而言需要在账本上计入一笔贷方金额。未来的某一天Tom取回了25美元银行不会直接把100美元修改成75美元而是在同一个账本上新增一笔借方金额25美元。从这个例子中可以看出账本是一种特殊的数据存储方式它不允许修改历史数据要改变账户的余额只能通过新增和追加记录来实现。区块链是与账本存在共同特征的数据库新的数据只能通过追加的方式进行存储没有任何修改历史数据的可能。因为不能修改历史记录所以区块链具有较高的可信任性、透明性和公正性。区块链是由区块组成的一个链条。这意味着它是由多个区块前后连接在一起的而交易记录则是保存在每个区块的内部采用这种方式后这些交易记录就不可能再被更改。由于去中心化和分布式特性区块链具有稳定性、健壮性、持久性和高可用性的特点不存在单点故障的问题。没有单个节点或服务器能控制整个链上的数据因此人人都能够参与其中成为区块链社区的参与者。
1.1区块链的用途
信任 区块链可以用于创建去中 心化应用实现数据由 人集体控制 其中的任何一个人都没有权力去更改或删除以前的记录 即使有人确实 做到了他产生的数据也不会被其 参与者接受自治性 对于区块链上的应用来说没有唯一的所有者 由于没有唯一 的所有者也就没有人能够单独控制它 但是每个人却都可以通过它的 行为来参与治理过程这就有利于建立 个不能被操控或不易诱发腐败 的解决方去中介化 基于 块链的应用能够消除现有流程的中间环节 例如在车 辆登记 、驾照发放等场景 中 会存 个中间角色它承担着车辆登记和驾照发放的职 如果 于区块链来设计流程那么这个中间角 色就没有存在的必要了因为区块链上的数据在被确认后驾照就会自 动签发车辆就会被自动登记 区块链将开启一个新的时代很多业务 不再需要中间的权威机构进行背书了
2.加密技术
2.1 散列
散列是将输入的数据转换成一个固定长度的随机字符串(散列值)的过程但是不能从结果反向生成或识别出原始数据因此散列也被称为数据指纹。几乎不可能基于其散列值导出输入数据哪怕原始数据发生了一点点的变化也将产生完全不同的散列值这样就确保了没有人敢在原始数据上做手脚。散列还有另外一个特征虽然输入的字符串数据可能长短不同但产生的散列值长度是固定的。例如使用SHA256散列算法不论输入数据的长度大小如何总会产生一个256个字节的散列值。当数据量很大时这一点就非常有用了它总能产生一个256个字节的散列值这样可以保存下来作为证据。以太坊在很多地方使用了散列技术它会对每一笔交易进行散列会对两个交易的散列值进行再次散列最终为同一区块内的每个交易产生一个根散列值。
散列还有一个重要特征就是从数学上来看两个不同的输入数据不会产 生同一个散列值。
在线哈希计算器:在线哈希值计算
2.2数字签名
前面我们介绍了非对称加密它的一个重要应用就是在数字签名创建和验证时使用非对称密钥。数字签名类似于一个人在纸上手写的签名。与手写签名的作用一样数字签名有助于识别一个人还有助于确保信息在传递过程中不被篡改。让我们举个例子来理解数字签名。 Alice准备给Tom发送一条信息。那么问题来了Tom如何确保收到的信息是由Alice发出来的如何确保信息在传递过程中没有被篡改过?解决方案就是不能发送原始的信息/交易Alice首先需要取得发送的信息的散列值然后用她的私钥对散列值进行加密最后她把这个刚产生的数字签名附加在散列值后发送给Tom。Tom收到信息后他使用Alice的公钥提取出数字签名并解密找到原始散列值。同时他从实际接收到的信息中提取散列值并对两个散列值进行比较如果两个散列值一致那么说明信息在传递过程中没有被篡改过。 数字签名通常用于资产或加密数字货币(例如以太币)的所有者对交易进行签名确认。
身份的辨别(公钥和私钥)
确保数字不被篡改(哈希)
3.区块链和以太坊架构
区块链与智能合约之间的桥梁以太坊 具体详情请点击旁边以太坊的链接
以太坊是区块链但不仅仅是区块链它在区块链的基础上架构了一个虚拟机可以在这个虚拟机上用以太坊指定的语言运行程序这个指定的语言是solidty程序即智能合约。
区块链是一种包含多个组件的体系结构区块链独特的地方在于这些组件 的功能和相互作用 重要的组件包括 EVM ( Ethereum Virtual Machine 以太坊 虚拟机、矿工、区块、交易、共识算法、账户、智能合约、挖矿、以太币和 gas 一个区块链网络是由大量的节点构成的其中 部分是属于矿工的挖矿 节点另一部分节点不挖矿但会帮助执行智能合约和交易 这些节点统称为 EVM 网络上的各个节点之间互相连接节点之间通过 P2P 协议进行通信默 认情况下使用 30303 端口 每个节点都维护着 个账本的实例副本包含链上的全部区块 由于网 络上存在大量矿工节点为了避免节点之间的区块数据存在差异这些节点会 持续同步区块确保账本数据一致
以太坊虚拟机EVM是智能合约的运行环境。
以太坊相当于分散在世界各地的节点共同组成的公共电脑 3.1以太币
在以太坊这个公共电脑上运行程序就像是在网吧上网必须要付费这个地方不是付人名币而是以太币。以太币采用十进制的计量体系其最小的单位是 wei 下面列出了一些计 量单位可 以在网站 https: //g ithub.com/e thereum/we b3.js blob/ 0.15 .O/lib/utils/ utils. js#L40 上查到更多信息。
3.2gas
也可以把以太坊理解成联通全球的道路网智能合约在上面运行就像是在这个道路上面开车需要耗费汽油。
3.3以太坊节点
以太坊客户端是一个软件应用程序它实现了以太坊规范并通过点对点网络与其他以太坊客户端进行通信。不同的以太坊客户端如果符合参考规范和标准化的通信协议就可以实现互操作。虽然这些不同的客户端是由不同的团队用不同的编程语言实现的但它们都 说 着相同的协议遵循相同的规则。因此它们都可以用来操作和与同一个以太坊网络进行交互一个节点需要运行两种客户端软件共识客户端和执行客户端。
执行客户端也称为执行引擎、EL 客户端或旧称“以太坊 1”客户端侦听网络中广播的新交易并在以太坊虚拟机中执行它们并保存所有当前以太坊数据的最新状态和数据库。共识客户端也称为信标节点、CL 客户端或旧称“以太坊 2”客户端实现权益证明共识算法使网络能够根据来自执行客户端的经验证数据达成一致。 此外还有名为“验证者”的第三种软件它们可被添加到共识客户端中使节点能参与保护网络安全。 作用:连接以太坊网络
在区块链和以太坊中每个区块都连接着另外一个区块 两个区块之间是 对父子的关系并且是 的关系这样首尾相接就组成了 个链条 章后面会讲到区块在接下来这张图中我 3个区块 区块1 区块2区块3 来示意 区块1 是区块1 的父区块区块2 是区块3 的父区块 在每个 区块的头部都存储了父区块的散列值这样就建立了父子关系
区块2 在头部存储了区块 1的散列值区块 3在头部存储了区块2 的散列 值以太坊有个创世区块的概念 它就是第一个区块 这个区块是在链初次发起时·自动创建的 你也可以这样认 为整个链条是由创世区块通过 genesis jso 文件来生成作为第一个区 块而开始启动的如下图所示 3.4以太坊账户
具体详情请点击上面以太坊账户的链接
帐户是存储以太币之处。 用户可以初始化帐户将以太币存入帐户并将自己帐户中的以太币转账给其他用户。 帐户和帐户余额存储在以太坊虚拟机中的一个大表格中是以太坊虚拟机总体状态的一部分。
以太坊有两类账户(它们共用同一个地址空间):
外部账户 由公钥-私钥对(也就是人)控制合约账户 由和账户一起存储的代码控制
外部账户的地址是由公钥决定的而合约账户的地址是在创建合约时确定的
相同点:
每个账户都有一个键值对形式持久化存储其中key和value的长度都是256位我们称之为存储
3.5交易
具体详情请点击上面交易的链接
交易是由帐户发出带密码学签名的指令。 帐户将发起交易以更新以太坊网络的状态。 最简单的交易是将 ETH 从一个帐户转到另一个帐户。
以太坊交易是指由外部持有帐户发起的行动换句话说是指由人管理而不是智能合约管理的帐户。 例如如果 Bob 发送 Alice 1 ETH则 Bob 的帐户必须减少 1 ETH而 Alice 的帐户必须增加 1 ETH。 交易会造成状态的改变。 端到端的交易
前面介绍了区块链和以太坊的一些基本知识接下来我们介绍一个完整的端到端的交易流程看看交易如何贯穿多个组件并保存到账本中 本例中Sam打算发送一个数字资产(如美元)给Mark。首先Sam新建了一个交易里面包括了from、to、value等字段数据然后发送到以太网络上该交易并没有立即写入到账本中而是暂存到交易池中。 挖矿节点新建了一个区块然后按照gas上限标准从交易池中提取交易(Sam的交易也将被提取),并添加到区块中网络上的全体矿工都在执行相同的任务。 接下来矿工们开始争先恐后地去计算难题在一段时间(或几秒)后获胜者(第一个解决难题的人)会发出通知声称他找到了答案赢得了比赛需要向区块链写入区块与此同时获胜者将答案添加到区块上并发送给其他矿工。其他矿工收到通知后首先验证这个答案一旦认定该答案确实有效就立即停止自己的计算接收这个包含了Sam的交易的区块然后添加到他们的本地账本中。这样下来就在链上产生了一个新的区块它将一直跨越时间和空间而永久的存在下去。在这期间双方的账户余额都会得到更新最后区块被分发复制到网络上的全部节点。这个过程如下图所示 以太坊上支持的3 种交易类型
1. 从一个账户向另外一个账户发送以太币 这个账户可能是外部账户或者 合约账户
2. 智能合 外部账户在 EVM 上部署合约是通过交易的方式实现的。
使用或借助合约内的函数 如果需要执行合约内的函数去改变一个状态 就需要一个交易如果执行函数没有改变任何一个状态就不需要交易
下面介绍与交易有关的一些重要属性
From 账户属性说明了这个账户是交易的发起方发送 gas 或以太币 前面 章节我们介绍过以太币和 gas 的概念 From 账户可以是外部账户或合约账户To 账户属性指的是接收以太币或其 收益的账户它可以是外部账户或合 约账户 如果是部署合约的交易则To 字段为空Value 账户属性指的是账户之间转移的以太币数量。Input 账户属性指的是合约编译后被部署在 EVM 上的字节码 input 用于保存有关智能合约函数带参调用的信息 下图展示了在典型的以太坊交易 中使用智能合约函数的地方从这个截图上看请注意 Input 字段中包含了带 有参数的函数调用BlockHash 账户属性指的是该交易所属的区块的散列值BlockNurnber 账户属性指的是交易所属的区块序号Gas 账户属性指的是交易的发送方支付的 gasGasPrice 账户属性指的是发送方支付的 gas 价格以 wei 为单位在本 章前面介绍以太币的 方提到过 we 的概念 总的 gas 消耗gas数量* gas 价格Hash 账户属性指的是交易的散列值Nonce 账户属性指的是交易的编号它由发送方在当前交易之前产生Transaction nde 账户属性指的是区块中当前交易的流水号Value 账户属性指的用 wei 计算的传递的以太的数量v,r,s属性指的是数字签名和交易的签名
3.6区块
区块是指一批交易的组合并且包含链中上一个区块的哈希。 这将区块连接在一起成为一个链因为哈希是从区块数据中加密得出的。 这可以防止欺诈因为以前的任何区块中的任何改变都会使后续所有区块无效而且所有哈希都会改变所有运行区块链的人都会注意到。 区块有很多属性为了便于掌握关键内容下面只介绍一些重要的部分
Difficulty 属性指的是矿工为了挖到这个区块而需要面对的计算难度GasLimit 属性指的是区块允许的 gas 总量上限 它决定了区块中能包含 多少个交易Gas Used 属性指的是区块中的交易实际消耗的 gas 数Hash 属性指的是这个区块的散列值Nonce 属性指的是一个数字它是解决难题的答案Miner 属性指的是矿工的账户可以用 co in base etherbase 的地址Number 属性指的是该区块在区块链上的序号ParentHash 属性指的是父区块的散列值ReceiptsRoot stateRoot TransactionsRoot 属性指的是在前 面的挖矿流程中提到的 merkle树Transactions 属性指的是区块中的交易组成的 个数组TotalDifficulty 属性指的是区块链的整体难度
3.7存储内存和栈
以太坊虚拟机有三个区域来存储数据:存储(storage),内存(memory)和栈(stack) 存储:每个账户有一块持久化内存区称为存储。存储是将256位字映射到256位字的键值存储区。在合约中枚举存储是不可能的且读存储的是相对开销很高修改存储的开销甚至更高。合约智能读写存储区内属于自己的部分。内存:合约会试图为每一次信息调用获取一块被重新擦拭干净的内存实例。内存是线性的可按字节级寻址但读的长度被限制为256位而写的长度可以是8位或者256位。当访问无论是读还是写之前访问过的内存字(word)时(无论是便宜到该字内的任何位置),内存将按字进行扩展(每个字是256位)。扩容也将消耗一定的gas。随着内存使用量的增长其费用也会增高(以平方级别)。栈:所有计算都在一个被称为栈(stack)的区域执行。栈最大1024个元素每个元素长度是一个字(256位)。对栈的访问只限于其顶端 二.智能合约的介绍 1.合约
合约是经过双方或多方同意约定立即执行或在将来执行一项交易的法律文件。因为合约是法律文件所以它具有强制性和可执行性。合约应用的场景很多例如一个人和保险公司签订合同购买健康险一个人从另外一个人手里购买一块土地个公司出售股权给另外一家公司
2.智能合约
具体详情请点击上面智能合约的链接
智能合约只是一个运行在以太坊链上的一个程序。 它是位于以太坊区块链上一个特定地址的一系列代码函数和数据状态。
智能合约也是一个以太坊帐户我们称之为合约帐户。 这意味着它们有余额可以成为交易的对象。 但是他们无法被人操控他们是被部署在网络上作为程序运行着。 个人用户可以通过提交交易执行智能合约的某一个函数来与智能合约进行交互。 智能合约能像常规合约一样定义规则并通过代码自动强制执行。 默认情况下您无法删除智能合约与它们的交互是不可逆的。
3.编写智能合约
编写智能合约的工具Visual Studio。
Remix 打开 http:// remix. ethereum. org 网页就可以 直接使用。可以在浏览 器上进行智能合约的创建、开发、部署和调试 合约维护有关的操作如 创 建、发布、调试都可以在同一个环境下完成而不需要切换到其他的窗口或 页面。
4.Remix的具体使用
打开 remix.ethereum.org 网址在浏览器中默认打开一个智能合约 2.新建一个合约选择左边菜单栏中的.对这个 Sol iy 文件进行命名以 sol 作为后缀 输入合约名字 Hello orld 点击“ OK ”就创建了 白合约 3.在制作 内的空白处输入下面这段代码就能创建你的第一个合约.
你可以使用关键词contract 创建合约声明全局状态变量和函数保存合约为后缀名是 sol的文件。在下面的源代码片段中当 Get elloWorld 数调 HelloWorld合约时将返回 Hello World 字符。其中确保版本号与开头pragma solidity ^0.8.24版本号相同。 // SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract HelloWeb3{string public _string Hello Web3!;
}
我们拆解程序学习 Solidity 代码源文件的结构 第 1 行是注释说明代码所使用的软件许可license这里使用的是 MIT 许可。如果不写许可编译时会出现警告warning但程序仍可运行。Solidity 注释以“//”开头后面跟注释内容注释不会被程序执行。 // SPDX-License-Identifier: MIT 第 2 行声明源文件所使用的 Solidity 版本因为不同版本的语法有差异。这行代码表示源文件将不允许小于 0.8.4 版本或大于等于 0.9.0 的编译器编译第二个条件由 ^ 提供。Solidity 语句以分号;结尾。 pragma solidity ^0.8.4; 第 3-4 行是合约部分。第 3 行创建合约contract并声明合约名为 HelloWeb3。第 4 行是合约内容声明了一个 string字符串变量 _string并赋值为 Hello Web3!。
contract HelloWeb3 {string public _string Hello Web3!;
} 5.编译与部署智能合约
在 Remix 编辑代码的页面按 Ctrl S 即可编译代码非常方便。
编译完成后点击左侧菜单的“部署”按钮进入部署页面。 默认情况下Remix 会使用 Remix 虚拟机以前称为 JavaScript 虚拟机来模拟以太坊链运行智能合约类似在浏览器里运行一条测试链。Remix 还会为你分配一些测试账户每个账户里有 100 ETH测试代币随意使用。点击 Deploy黄色按钮即可部署我们编写的合约。 部署成功后在下方会看到名为 HelloWeb3 的合约。点击 _string即可看到 Hello Web3!。
三.Solidity中的变量类型 值类型(Value Type)包括布尔型整数型等等这类变量赋值时候直接传递数值。 引用类型(Reference Type)包括数组和结构体这类变量占空间大赋值时候直接传递地址类似指针。 映射类型(Mapping Type): Solidity中存储键值对的数据结构可以理解为哈希表
1.值类型
1.1布尔型
布尔型是二值变量取值为 true 或 false。
// 布尔值
bool public _bool true;
布尔值的运算符包括 ! 逻辑非 逻辑与and || 逻辑或or 等于 ! 不等于 // SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract HelloWeb3{string public _string Hello Web3!;bool public _bool true;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) 是 trueg(y) 不会被计算即使它和 f(x) 的结果是相反的。假如存在f(x) g(y) 的表达式如果 f(x) 是 falseg(y) 不会被计算。所谓“短路规则”一般出现在逻辑与和逻辑或||中。 当逻辑或的第一个条件为false时就不会再去判断第二个条件 当逻辑与||的第一个条件为true时就不会再去判断第二个条件这就是短路规则。
1.2整型
整型是 Solidity 中的整数最常用的包括
// 整型
int public _int -1; // 整数包括负数
uint public _uint 1; // 正整数
uint256 public _number 20220330; // 256位正整数
常用的整型运算符包括 比较运算符返回布尔值 ! 算数运算符 - * / %取余**幂
// 整数运算
uint256 public _number1 _number 1; // -*/
uint256 public _number2 2**2; // 指数
uint256 public _number3 7 % 2; // 取余数
bool public _numberbool _number2 _number3; // 比大小
1.3地址类型
地址类型(address)有两类 普通地址address: 存储一个 20 字节的值以太坊地址的大小。 payable address: 比普通地址多了 transfer 和 send 两个成员方法用于接收转账。
// 地址
address public _address 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71;
address payable public _address1 payable(_address); // payable address可以转账、查余额
// 地址类型的成员
uint256 public balance _address1.balance; // balance of address 1.4定长字节数组
字节数组分为定长和不定长两种 定长字节数组: 属于值类型数组长度在声明之后不能改变。根据字节数组的长度分为 bytes1, bytes8, bytes32 等类型。定长字节数组最多存储 32 bytes 数据即bytes32。 不定长字节数组: 属于引用类型之后的章节介绍数组长度在声明之后可以改变包括 bytes 等。
// 固定长度的字节数组
bytes32 public _byte32 MiniSolidity;
bytes1 public _byte _byte32[0];
在上述代码中MiniSolidity 变量以字节的方式存储进变量 _byte32。如果把它转换成 16 进制就是0x4d696e69536f6c69646974790000000000000000000000000000000000000000
_byte 变量的值为 _byte32 的第一个字节即 0x4d。 1.5枚举enum
枚举enum是 Solidity 中用户定义的数据类型。它主要用于为 uint 分配名称使程序易于阅读和维护。它与 C 语言 中的 enum 类似使用名称来代替从 0 开始的 uint
// 用enum将uint 0 1 2表示为Buy, Hold, Sell
enum ActionSet { Buy, Hold, Sell }
// 创建enum变量 action
ActionSet action ActionSet.Buy;
枚举可以显式地和 uint 相互转换并会检查转换的正整数是否在枚举的长度内否则会报错
// enum可以和uint显式的转换
function enumToUint() external view returns(uint){return uint(action);
}
enum 是一个比较冷门的变量几乎没什么人用。 2.函数
Solidity语言的函数非常灵活可以进行各种复杂操作。在本教程中我们将会概述函数的基础概念并通过一些示例演示如何使用函数。
我们先看一下 Solidity 中函数的形式:
function function name(parameter types) {internal|external|public|private}
[pure|view|payable] [returns (return types)]
看着有一些复杂让我们从前往后逐个解释(方括号中的是可写可不写的关键字) function声明函数时的固定用法。要编写函数就需要以 function 关键字开头。 function name函数名。 (parameter types)圆括号内写入函数的参数即输入到函数的变量类型和名称。 {internal|external|public|private}函数可见性说明符共有4种。 public内部和外部均可见。 private只能从本合约内部访问继承的合约也不能使用。 external只能从合约外部访问但内部可以通过 this.f() 来调用f是函数名。 internal: 只能从合约内部访问继承的合约可以用。 注意 1合约中定义的函数需要明确指定可见性它们没有默认值。 注意 2public|private|internal 也可用于修饰状态变量。public变量会自动生成同名的getter函数用于查询数值。未标明可见性类型的状态变量默认为internal。 [pure|view|payable]决定函数权限/功能的关键字。payable可支付的很好理解带着它的函数运行的时候可以给合约转入 ETH。pure 和 view 的介绍见下一节。 [returns ()]函数返回的变量类型和名称。
2.1 Pure 和View讲解
刚开始学习 solidity 时pure 和 view 关键字可能令人费解因为其他编程语言中没有类似的关键字。solidity 引入这两个关键字主要是因为 以太坊交易需要支付气费gas fee。合约的状态变量存储在链上gas fee 很贵如果计算不改变链上状态就可以不用付 gas。包含 pure 和 view 关键字的函数是不改写链上状态的因此用户直接调用它们是不需要付 gas 的注意合约中非 pure/view 函数调用 pure/view 函数时需要付gas。
在以太坊中以下语句被视为修改链上状态 写入状态变量。 释放事件。 创建其他合约。 使用 selfdestruct. 通过调用发送以太币。 调用任何未标记 view 或 pure 的函数。 使用低级调用low-level calls。 使用包含某些操作码的内联汇编。
为了帮助大家理解我画了一个马里奥插图。在这幅插图中我将合约中的状态变量存储在链上比作碧琪公主三种不同的角色代表不同的关键字。 pure中文意思是“纯”这里可以理解为”纯打酱油的”。pure 函数既不能读取也不能写入链上的状态变量。就像小怪一样看不到也摸不到碧琪公主。 view“看”这里可以理解为“看客”。view函数能读取但也不能写入状态变量。类似马里奥能看到碧琪公主但终究是看客不能入洞房。 非 pure 或 view 的函数既可以读取也可以写入状态变量。类似马里奥里的 boss可以对碧琪公主为所欲为。 2.2代码解析
1. pure 和 view
我们在合约里定义一个状态变量 number初始化为 5。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract FunctionTypes{uint256 public number 5;
}
定义一个 add() 函数每次调用会让 number 增加 1。
// 默认function
function add() external{number number 1;
}
如果 add() 函数被标记为 pure比如 function add() external pure就会报错。因为 pure 是不配读取合约里的状态变量的更不配改写。那 pure 函数能做些什么举个例子你可以给函数传递一个参数 _number然后让他返回 _number 1这个操作不会读取或写入状态变量。
// pure: 纯纯牛马
function addPure(uint256 _number) external pure returns(uint256 new_number){new_number _number 1;
} 如果 add() 函数被标记为 view比如 function add() external view也会报错。因为 view 能读取但不能够改写状态变量。我们可以稍微改写下函数读取但是不改写 number返回一个新的变量。
// view: 看客
function addView() external view returns(uint256 new_number) {new_number number 1;
} 2. internal v.s. external
// internal: 内部函数
function minus() internal {number number - 1;
}// 合约内的函数可以调用内部函数
function minusCall() external {minus();
}
我们定义一个 internal 的 minus() 函数每次调用使得 number 变量减少 1。由于 internal 函数只能由合约内部调用我们必须再定义一个 external 的 minusCall() 函数通过它间接调用内部的 minus() 函数。 3. payable
// payable: 递钱能给合约支付eth的函数
function minusPayable() external payable returns(uint256 balance) {minus(); balance address(this).balance;
}
我们定义一个 external payable 的 minusPayable() 函数间接的调用 minus()并且返回合约里的 ETH 余额this 关键字可以让我们引用合约地址。我们可以在调用 minusPayable() 时往合约里转入1个 ETH。 我们可以在返回的信息中看到合约的余额变为 1 ETH。 我们介绍了 Solidity 中的函数。pure 和 view 关键字比较难理解在其他语言中没出现过view 函数可以读取状态变量但不能改写pure 函数既不能读取也不能改写状态变量。