主页 > 如何下载imtoken钱包 > 以太坊智能合约开发-《精通以太坊智能合约开发》学习总结实践
以太坊智能合约开发-《精通以太坊智能合约开发》学习总结实践
文章目录
一、以太坊智能合约初探 1. Remix小demo
Remix,Remix是以太坊官方开源的Solidity在线集成开发环境。 可以使用Solidity语言在网页中完成以太坊智能合约的在线开发、在线编译、在线测试、在线部署、在线调试和在线交互。 非常适合Solidity智能合约学习和快速原型开发。
目前尝试 Solidity 编程的最佳方式是使用 Remixo Remix 是一个基于浏览器的 Solidity IDE,它集成了 Solidity 编译器、运行时以及调试和发布工具。
用浏览器打开网址
官方演示
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.8.0;
/**
* @title Storage
* @dev Store & retrieve value in a variable
*/
contract Storage {
uint256 number;
/**
* @dev Store value in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
}
/**
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
}
合约代码分析
与大多数语言不同,函数在访问状态变量时不需要在其他语言前面加上this前缀。
合约名、函数名、变量名等所有标识符只能使用ASCII字符集中的字符,但UTF-8编码的数据可以存储在字符串变量中。
2. 编写智能合约的编程语言
只需使用 Solidity。 编写智能合约有几种语言可供选择: Solidity,有点类似于Javascript,文件扩展名为.sol。 Serpent 接近 Python,文件名以 .se 结尾。 还有一个类似 Lisp 的 LLL。 Serpent流行了一段时间,但是现在最流行和稳定的是Solidity,所以Solidity好。
在 Solidity 合约被编译并发送到网络后,您可以使用以太坊的 web3.js JavaScript API 调用它并构建一个可以与之交互的 Web 应用程序。
二、以太坊的核心概念 1. 交易/交易(Transaction)
注:英文Transaction多数场合译为“交易”,表达数据库特性时译为“交易”。
区块链是一个全球共享的交易数据库。 全球共享意味着参与这个网络的每个人都可以阅读其中的记录。 如果你想修改这个数据库中的内容,你必须创建一个由其他人确认的交易。 事务意味着要进行的修改(如果要同时修改两个值 )只能全部应用或根本不应用。
例如,假设有一个表格,其中列出了电子货币中所有账户的余额。 当从一个账户到另一个账户的转账请求发生时,该数据库的交易性质确保从一个账户中减去的金额被添加到另一个账户中。 如果由于某种原因,无法执行向目标账户添加金额的操作,则原账户中的金额不会发生变化。
2.积木
一个区块是若干笔交易的集合,它会被标记上一个时间戳和前一个区块的哈希标识符。 在对区块进行哈希处理后,会生成工作量证明来验证区块中的交易。 全网共识后,有效区块将被追加到区块链中。
这些区块在时间上形成一个线性序列,这就是区块链这个词的来源。 块定期添加到链中。 对于以太坊,这个间隔大约是 17 秒。
有时可能会发生块作为“顺序选择机制”(也称为挖掘)的一部分回滚的情况,但通常只在链的“末端”。 最后添加的块越多,回滚的可能性就越小。 因此,交易有可能被回滚甚至从区块链中删除,但您在交易发生后等待的时间越长,这种情况发生的可能性就越小。
3.共识协议:工作量证明(PoW)
在工作量证明系统中,创建块的过程称为“挖矿”。矿工是
在网络中挖掘区块的节点。
任何人都可以成为网络中的矿工。 每个矿工独立解决数学难题,第一个解决难题的矿工是赢家,他的奖励是5 ETH和区块中所有交易的交易手续费。 如果一个矿工的处理器比网络中的其他节点更强大,并不意味着这个矿工一定会成功,只是成功的概率会更高。 事实上,以太坊的网络安全性是通过网络的总计算能力来衡量的。
4.股权证明(PoS)
以太坊最终将转向权益证明,以解决工作量证明的资源密集型问题
问题。 权益证明的主要思想是:作为验证节点,首先要有一定数量的以太币,
根据ETH的数量和时间,会产生投注和验证区块的权益。 只有拥有权益的节点才能有效地验证区块。 当经过验证的区块被打包入链后,将获得与其权益成比例的区块奖励。 如果验证了恶意或错误的块,则将扣除下注权益。
5. 以太坊虚拟机(EVM)
以太坊虚拟机是由沙箱封装的完全隔离的运行环境。 **在 EVM 内部运行的代码无法访问网络、文件系统或其他进程,**即使是智能合约也只能与其他智能合约进行有限的交互。
但是以太坊周末交易吗,以太坊虚拟机本身运行在以太坊节点上。 当我们将合约部署到以太坊网络时,合约可以运行在所有以太坊网络节点的以太坊虚拟机上。
编译合约
以太坊虚拟机上运行的是合约的字节码形式,部署前需要检查合约。
要编译,您可以选择使用 Remix 或 sole 编译器。
6. 以太坊账户
参考网址:
以太坊中的两种账户:外部账户和合约账户
以太坊中有两种类型的账户,如下图所示:
以太坊中的账户由四个字段组成:随机数、账户余额、合约代码(如果有)和存储空间(通常为空)。
与比特币区块中存储的交易不同,对应以太坊账户的状态以默克尔帕特里夏树(Merkle Patricia Tree,MPT)的形式存储在以太坊区块中。
以太坊中的交易是所谓的状态转换函数。 一笔交易触发它的执行,将相应的账户从一个状态转换到一个新的状态,然后将新的状态存储在区块链的一个数据块中。
只有合约账户才有code,里面存放的是codeHash(该账户的以太坊虚拟机代码的哈希值)。 该字段生成后不可变,即智能合约代码不可变。
外部账户可以触发交易,而合约账户不能主动发起交易,只能在被触发后根据预先编写的智能合约代码执行。 与外部账户不同,合约账户不能自己发起交易。 但是合约账户可以触发另一笔交易以响应一笔交易。 因此以太坊周末交易吗,以太坊上的任何动作都是由外部账户触发的交易所发起的(即动作的发起者必须是外部账户)。
合约账户可以设置多重签名(multisign)。 例如,一个简单的例子是:有一个现有的合约账户,需要一笔转账由发起转账的人(Alice)和另一个人(Charles)签名。 因此,当Alice通过这个合约转给Bob 20 ETH时,合约会通知Charles签字,Bob签字后就可以收到这20 ETH(见图)。
7.以太坊钱包
Geth 是以太坊官方提供的客户端(钱包)。 它是开发智能合约的常用工具之一。 它是基于Go语言开发的。
Geth提供了交互式命令控制台,可以通过接口命令获取
节点信息与智能合约良好交互。
另一个常用的钱包是 MetaMask,它是一个浏览器插件,可以与 Remix 一起使用来部署和执行智能合约。 与 Geth 相比,MetaMask 不需要同步节点数据,使用起来非常方便。
8. 存储、内存和堆栈
每个帐户都有一个称为存储的持久存储区域。 以键值对的形式存储,键和值的长度均为256位。 账户的存储不能在合约中遍历。
存储读写操作开销(消耗的gas量)大,修改操作开销更大。 合约只能读写自己的存储。
第一个存储区域称为内存。当合约执行每个消息调用时,它有
一块被擦除的新记忆。 内存是线性的,可以以字节为粒度寻址。 但读长度限制为32字节(256位),写长度可以是l字节或32字节。
当访问(无论是读还是写)一个之前从未被访问过的内存字(word)时(不管该字内任何位置的偏移量),内存按word扩展(每个word为32字节)扩展也会消耗一定量的气体。 随着内存使用量的增加,它的成本也会增加(在正方形级别增加)。
第二个存储区叫做栈(stack),EVM不是基于寄存器,而是基于栈的虚拟
虚拟机,因此所有计算都在称为堆栈的区域中执行。 堆栈最多有1024个元素,每个元素256位。 一次只能访问栈顶元素。 限制是通过以下方式完成的:允许将顶部 16 个元素之一复制到堆栈顶部,或者将堆栈的顶部元素与底部 16 个元素之一交换。 其他所有操作只能取最顶层元素(一个或两个或多个元素,视具体操作而定),操作后将结果压入栈顶。 当然你也可以把栈上的元素放入storage或者内存中。 但是不可能只访问栈上指定深度的元素,除非其他元素先从栈顶移除。
9. 自毁
合约代码从区块链中移除的唯一方式是合约对合约地址进行自毁操作; 合约账户中剩余的以太币将被发送到指定的目标,然后其存储和代码将从状态中移除
3.Solidity合约内容
官网参考:
合约就像一个类,它包含状态变量、函数、函数修饰符、事件、结构和枚举。 通过在编译时备份代码,合约还支持继承。 最后,合约还支持多态性。
4. Solidity数据类型
强烈推荐官网参考:
Solidi 是一种静态类型语言。 常见的静态类型语言包括C、C++、Java等,静态类型是指每个变量(局部或状态变量)都需要在编译时指定(或者至少可以推导出类型)。
Solidity 类型非常关心它们占用的空间大小。 另外,Solidity的一些基本类型可以组合成复杂类型。 Solidity类型分为两类:值类型(Value Type)和引用类型(Reference Type)。
值类型
官网参考:
值类型是指在传递这些类型时,传递的是类型的值。 值类型占用的空间在32字节以内,值类型变量在赋值或传递参数时总是进行值拷贝。
值类型包括:
• 布尔型(Boolean)
• 整数 Clnteger )
• 定长浮点数(Fixed Point Number)
• 固定大小的字节数组
• 有理数和整数文字
• 字符串文字(String Literal)
• 十六进制文字
• 枚举 CEnum )
• 函数类型(函数类型)
• 地址类型(Address)
• 地址字面量(Address Literal)
引用类型
官网参考:#reference-types
引用类型主要包括:数组(Array)、结构(Struct)和映射(Mapping)。
函数类型
Solidity 中的函数也可以是类型并且是值类型。 您可以将函数分配给函数类型的变量,将函数作为参数传递,并在函数调用中返回函数。 下面是将函数分配给变量的示例。
函数类型有两种:内部(internal)函数和外部(external)函数。
内部和外部表示调用方法及其可见性。 很多人在写传统程序的时候不太注意可见性。 但是,在编写智能合约的时候,大家要特别注意。 如果使用internal而使用external,很容易造成安全问题,增加gas消耗。
选择器成员属性
一个公共或外部(public/external)函数类型都有一个特殊的成员属性选择器,它对应一个ABI函数选择器,这里你只需要知道它是一个函数签名)。
如何区分合约地址和外部账户地址
判断一个地址是合约地址还是外部账户地址
参考网址:
判断一个地址是合约地址还是外部账户地址
扩展代码大小
获取地址关联码长度。 合约地址长度大于0,外部账户地址为0
//pragma solidity ^0.4.18;
//extcodesize获取地址关联代码长度 合约地址大于0 外部账户地址为0
contract IsCadd {
function isContract(address addr) returns (bool) {
uint size;
assembly { size := extcodesize(addr) }
return size > 0;
}
}
5. Solidity 中的单元
智能合约语言Solidity教程系列7——以太币单位和时间单位
参考网址:
Solidity 中有两种单位:货币单位和时间单位。
1. 货币单位(以太币单位)
一个数字常量(字面量)后跟wei、finney、szabo或ether的后缀,后缀是货币单位。 可以转换不同的单位。 没有任何后缀的默认单位是wei。
不同以太币单位的换算关系如下:
1 以太 == 10^3 芬尼 == 1000 芬尼
1 以太 == 10^6 萨博
1 以太 == 10^18 wei
以太坊单位其实是一个密码学家的名字,以太坊创始人纪念他们在数字货币领域的贡献。 他们是:
2. 时间单位
时间单位:秒、分、时、日、周、年都可以作为后缀相互转换。 规则如下:
1 == 1 秒(默认为秒)
1 分钟 == 60 秒
1 小时 == 60 分钟
1 天 == 24 小时
1 周 = 7 天
1 年 = 365 天
使用这些单位的日期计算需要特别小心,因为不是每年都有 365 天,也不是每一天都有 24 小时,因为闰秒。 由于无法预测闰秒,因此必须通过外部神谕对其进行更新以获得准确的日历基准。
6. Solidity全局变量和函数
在使用solidity编写智能合约时,全局环境中总是存在一些特殊的变量和函数,整体分为几类。
区块与交易属性地址相关的合约相关
需要掌握如何获取区块和交易的属性,如何通过ABI编码函数获取编码数据,如何处理错误函数,以及数学和加密相关的函数,地址和合约相关的函数。
七、Solidity表达与控制结构