编写您的第一个区块链:学习扎实性

Solidity是在以太坊中编程合同的特定领域特定语言。 实际上,Solidity是最流行的以太坊编程语言。 还有其他以太坊的编程语言,例如蛇,Mutan和LLL。 Solidity的语法更接近JavaScript和C。

团结是一种静态类型的语言。 因此,在Solidity中,变量类型检查是在编译时执行的。 必须在编译时为每个变量(状态或局部变量)指定类型,这样做的好处是,所有验证和检查都在编译时完成,并且某些类型的错误(例如数据类型的解释)可以更早地捕获。在开发周期中而不是在运行时中,这可能会花费很大。 实际上,Solidity具有诸如继承,库和定义复合数据类型的功能。

此外,Solidity也被称为面向合同的语言。 从本质上讲,契约就像其他面向对象编程语言中的“类”一样。

种类

在Solidity中,数据类型有两类:值类型和引用类型。

值类型

值类型为:

布尔型

布尔数据类型有两个可能的值,true或false。 例如:

  bool v = true; 

在此示例中,为v分配了true值。

整数

此数据类型表示整数。 在Solidity中,有符号整数(int)和无符号整数(uint)。 从int8到int256,这意味着从int8到int256可用8个增量的关键字,例如int8,int16等。

有uint8到uint256。

在下一个示例中,uint是uint256的别名:

  uint256 x; uint y; int256 z; 

因此,也可以使用“ constant”关键字声明这些类型。 因此,编译器不会为这些变量保留存储插槽。 语法代码应如下所示:

 单位常数z = 10 + 10; 

此外,状态变量是在函数主体外部声明的,并且在整个合同中它们始终可用,这取决于分配给它们的可访问性以及合同持续存在的时间。

地址

地址数据类型保存一个160位长(20字节)的值。 实际上,该地址有几个成员,可用于与合同进行交互和查询合同。

这些地址的成员是:

· Balance:余额成员以Wei(以太的最小单位)返回地址的余额。

· 发送:发送成员用于将一定数量的以太发送到一个地址(以太坊的160位地址),并根据交易结果返回true或false。

例如,有一个地址为to和一个地址为from。 然后,有一个if语句,其中使用了balance和send memebers:

 地址到= 0x6414cc08d148dce9ebf5a2d0b7c220ed2d3203da;地址从=此;如果(to.balance  50)到send(20); 

通话功能

此外,提供了调用,调用代码和委托调用,以便与不具有应用程序二进制接口(ABI)的功能进行交互。 这些功能(调用,呼叫代码和委托调用)应谨慎使用,因为由于对合同类型安全性的影响,它们不安全使用。

数组值类型(固定大小和动态大小的字节数组)

在Solidity中,有固定大小和动态大小的字节数组。

固定大小的关键字范围从bytes1到bytes32。 此外,动态大小的关键字包括“字节”和“字符串”。 “字节”用于原始字节数据,“字符串”用于以UTF-8编码的字符串。 实际上,这些数组是通过值返回的,调用这些数组将产生gas成本(这是以太币的成本)。 “ length”是数组值类型的成员,并返回字节数组的长度。

下一个示例是静态(固定大小)数组:

  bytes32 [10] bankAccounts; 

下一个示例是动态调整大小的数组:

  bytes32 []交易; 

下一个示例是获取交易时间:

  trades.length; 

文字

文字用于表示固定值。

整数文字

整数文字是介于0到9之间的十进制数字序列。

例如:

  uint8 x = 2; 

字符串文字

字符串文字可指定一组用双引号或单引号引起来的字符。 例如:

  “包装”“包装” 

十六进制文字

十六进制文字以关键字hex为前缀,并在双引号或单引号内指定。

例如:

  (十六进制“ AABBCC”); 

枚举

枚举允许创建用户定义的类型。 例如:

  Order {Filled,Placed,Expired}; Order private ord; ord = Order.Filled; 

枚举允许向和从所有整数类型进行显式转换。

功能类型

在Solidity中,有两种功能类型:内部和外部功能。

内部功能

内部功能只能在当前合同的范围内使用。

外部功能

可以通过外部函数调用来调用外部函数。

在Solidity中,功能可以标记为常量。 此外,恒定功能无法更改合同中的任何内容。 常量函数仅在被调用(调用)时返回值,而不会花费任何精力。

声明函数的语法应如下所示:

 函数( ){内部|外部} [常量] [应付] [返回值( )]] 

参考类型

引用类型通过引用传递,并在以下部分中讨论。

数组

数组表示在内存位置布置的大小和类型相同的连续元素集。 此外,数组具有两个名为length和push的成员:

  uint [] OrderIds; 

结构

这些结构可用于将一组不同的数据类型归为一个逻辑组。 这些结构可用于定义新类型。 例如:

 结构交易{uint tradeid; uint数量; uint价格;字符串交易者;} 

资料位置

数据位置指定特定复杂数据类型的存储位置。 因此,有存储位置或内存位置。 数组和结构可以使用这些数据位置。 实际上,指定位置有时会有助于控制气体消耗。 此外,Calldata是另一个用于存储函数参数的内存位置。 实际上,外部函数的参数使用calldata存储器。 默认情况下,函数的参数存储在内存中,所有其他局部变量都使用存储。 实际上,使用存储需要状态变量。

对应

映射用于键到值的映射。 因此,映射用于将值与键关联。 此外,此映射中的所有值均已用全零初始化。 例如:

 映射(地址=> uint)提供; 

此映射示例显示报价被声明为映射。

现在,我们有另一个映射示例:

 映射(字符串=> uint)出价; bids [“ packt”] = 10; 

因此,映射就像字典或哈希表,其中字符串值映射为整数值。 实际上,映射(命名为bids)具有一个“ packt”字符串值,该值映射到值10。

全局变量

实体提供了许多全局变量,这些变量始终在全局名称空间中可用。 全局变量提供有关块和事务的信息。 此外,还提供密码功能和与地址相关的变量。

实际上,可用功能和变量的子集如下所示:

  keccak256(…)返回(bytes32) 

该函数用于计算提供给该函数的参数的keccak256哈希:

  ecrecover(bytes32 hash,uint8 v,bytes32 r,bytes32 s)返回(地址) 

因此,ecrecover函数从椭圆曲线签名中返回公钥的关联地址:

 块号 

本示例返回当前块号。

控制结构

在Solidity中,控制结构为if – else,为中断,继续,返回而做。

大事记

实体事件可用于在EVM日志中记录某些事件。 当要求外部接口通知合同中的任何更改或事件时,这些功能非常有用。 此外,这些日志存储在交易日志中的区块链上。 此外,无法从合同访问日志,而是将日志用作通知状态更改或合同中事件(满足条件)发生的机制。

在下一个示例中,如果传递给功能Matcher的x参数等于或大于10,则valueEvent事件将返回true。此示例代码如下所示:

 合同valueChecker {uint8 price = 10; event valueEvent(bool returnValue);函数Matcher(uint8 x)返回(bool){if(x> = price){valueEvent(true); return true;}}} 

遗产

在Solidity中,有继承。 “ is”关键字用于从另一个合同衍生合同。

例如,valueChecker2是从valueChecker合同派生的。 衍生合同可以访问父合同的所有非私有成员。 示例代码应如下所示:

 合同valueChecker {uint8 price = 10;事件valueEvent(bool returnValue);函数Matcher(uint8 x)返回(bool){if(x> = price){valueEvent(true); return true;}}}}合同valueChecker2是valueChecker {函数Matcher2()返回(uint){返回价格+ 10;}} 

在此示例中,如果将(uint8 price = 10)更改为(uint8 private price = 10),则valuechecker2合同将无法访问它,因为现在该成员被声明为private。 因此,不允许任何其他合同访问它。

图书馆

库仅在特定地址部署一次,并且它们的代码通过以太坊虚拟机(EVM)的CALLCODE / DELEGATECALL操作码调用。 库背后的关键思想是代码可重用性。 这些库类似于合同,并充当调用合同的基础合同。 例如:

 库添加{函数Add(uint x,uint y)返回(uint z){return x + y;}} 

然后可以在合同中调用该库。 首先,需要将其导入,并且可以在代码中的任何位置使用它。 例如:

 导入“ Addition.sol”函数Addtwovalues()返回(uint){返回Addition.Add(100,100);} 

实际上,库有一些限制。 例如,库不能具有状态变量,并且不能继承或继承。 此外,图书馆无法接收以太币。

功能

牢固的功能是与合同关联的代码模块。 函数使用名称,可选参数,访问修饰符,可选常量关键字和可选返回类型声明。 在下面的示例中显示:

函数orderMatcher(uint x)私有常量返回(布尔返回值)

在前面的示例中,函数是用于声明函数的关键字。 orderMatcher是函数名称,uint x是可选参数,private是访问修饰符/说明符,用于控制从外部合约对函数的访问,constant是可选关键字,用于指定此函数在合约中不更改任何内容,但是是仅用于从合同中检索值,而return(布尔返回值)是该函数的可选返回类型。

如何定义函数:定义函数的语法如下所示:

 函数()返回( ){} 

函数签名:牢固的函数由其签名标识,即其完整签名字符串的keccak-256哈希的前四个字节。 这在浏览器的稳定性上也是可见的,如以下屏幕截图所示。 D99c89cb是名为Matcher的函数的32字节keccak-256哈希的前四个字节。

区块链的统一语言

在此示例功能中,Matcher的签名哈希为d99c89cb。 此信息对于构建接口很有用。

函数的输入参数:函数的输入参数以 的形式声明。 此示例阐明了uint x和uint y是checkValues函数的输入参数的概念:

 合同myContract {function checkValues(uint x,uint y){}} 

函数的输出参数:函数的输出参数以 的形式声明。 此示例显示了一个返回uint值的简单函数:

  contract myContract {Function getValue()return(uint z){z = x + y;}} 

一个函数可以返回多个值。 在前面的示例函数中,getValue仅返回一个值,但是一个函数最多可以返回14个不同数据类型的值。 未使用的返回参数的名称可以选择省略。

内部函数调用:可以直接在内部调用当前合同上下文中的函数。 进行这些调用是为了调用同一合约中存在的功能。 这些调用导致在EVM字节码级别进行简单的JUMP调用。

外部函数调用:外部函数调用是通过从一个合同到另一个合同的消息调用进行的。 在这种情况下,所有功能参数都将复制到存储器中。 如果使用此关键字调用内部函数,则也将其视为外部调用。 此变量是引用当前合同的指针。 它可以显式转换为地址,并且合同的所有成员均从该地址继承。

后备函数:这是合同中没有参数的未命名函数,并且返回数据。 每当接收到ether时,该函数就会执行。 如果合同打算接收以太币,则必须在合同内执行; 否则,将引发异常并返回ether。 如果没有其他功能签名与合同匹配,则该函数也会执行。 如果预期该合同将收取以太币,则应使用payable修饰符声明后备功能。 应付账款为必填项; 否则,该功能将无法接收任何乙醚。 可以使用address.call()方法来调用此函数,例如,在以下示例中:

 函数(){throw;} 

在这种情况下,如果根据先前描述的条件调用了回退功能; 它会调用throw,它将状态回滚到进行调用之前的状态。 除了throw之外,它还可以是其他构造。 例如,它可以记录一个事件,该事件可用作警报,以将呼叫结果反馈给主叫应用程序。

修饰符函数:这些函数用于更改函数的行为,可以在其他函数之前调用。 通常,它们用于在执行功能之前检查某些条件或进行验证。 _(下划线)用于修饰符函数,在调用修饰符时将被函数的实际主体替换。 基本上,它表示需要保护的功能。 这个概念类似于其他语言中的警卫功能。

构造函数:这是一个可选函数,与合同同名,一旦创建合同即执行。 构造函数不能由用户稍后调用,并且合同中仅允许一个构造函数。 这意味着没有重载功能可用。

功能可见性说明符(访问修饰符):可以使用四个访问说明符来定义功能,如下所示:

外部的:可以从其他合同和交易中访问这些功能。 除非使用此关键字,否则不能在内部调用它们。

Public:默认情况下,函数是public。 可以在内部或使用消息来调用它们。

内部:内部功能对于从父合同衍生的其他合同可见。

私有:私有函数仅在声明它们的同一合同上可见。

其他重要的关键字/函数throw:throw用于停止执行。 结果,所有状态更改都将还原。 在这种情况下,因为所有剩余的气体都被消耗了,所以没有气体返回到交易发起者。

版本编译

为了解决将来可能会出现的Solidity编译器版本的兼容性问题,可以使用编译指示来指定兼容编译器的版本,例如,如下所示:

 实用度^ 0.5.0 

这将确保源文件不会使用小于0.5.0的版本以及从0.6.0开始的版本进行编译。

进口

实体导入允许将符号从现有的实体文件导入当前的全局范围。 这类似于JavaScript中可用的import语句,例如,如下所示:

 导入“模块名”; 

注释

注释可以以类似于C语言的方式添加到solidity源代码文件中。 多行注释包含在/ *和* /中,而单行注释以//开头。

下面是一个示例性的Solidity程序,其中显示了用法,导入和注释的用法。

想了解区块链吗? 咨询我们或通过我们的BigDataGuys区块链训练营之一接受培训。

主办公室:华盛顿特区西北康涅狄格大街1250号,邮编20036

电话:

202–897–1944 |

202–897–1966

对于培训— Training@Bigdataguys.com对于咨询-Info@Bigdataguys.com

推特https://twitter.com/BigDataGuys

Linkedin https://www.linkedin.com/company/13190381/

关于我https://about.me/bigdataguys

www.bigdataguys.com