Javascript和Solidity简介-第2部分:Solidity

在第一部分中,我们讨论了JavaScript,并向您展示了编程语言的基础知识。在第2部分中,我们将讨论Solidity以及如何利用这种编程语言来发挥自己的优势。在开始编码部分之前,请先了解一些有关坚固性的基础知识.

团结–简介

对于任何想学习如何制作DAPP(去中心化应用程序)或进入ICO游戏的人来说,学习Solidity是绝对必要的。 Solidity由Gavin Wood,Christian Reitwiessner,Alex Beregszaszi,Hiichi Hirai和几位以太坊前核心贡献者共同开发,以实现在以太坊等区块链平台上编写智能合约.

Solidity是一种故意精简的,松散类型的语言,其语法与JavaScript非常相似。您可以签出Solidity文档 就在这儿.

使用Solidity,您将对将在以太坊虚拟机(又称为EVM)中执行的智能合约进行编码。以太坊开发者提到分配给他们合约的一定数量的天然气。合同的每一行都需要一定数量的天然气才能执行。气体限制应足以使合同完全执行.

话虽如此,让我们开始编码.

混音– IDE

我们将在Remix上执行代码. 点击这里 进入Remix网站。 Remix是一个浏览器内环境,您可以在其中测试区块链上执行智能合约。这是由以太坊基金会自己创建的,因此您可以随时随地开始开发合同.

因此,当您进入该网站时,将看到以下屏幕:

Javascript和Solidity简介-第2部分:Solidity

现在,当您初次查看时,此UI可能会非常吓人。但是,让我们逐节细分。我们将从左边去.

Javascript和Solidity简介-第2部分:Solidity

浏览器的左侧具有您当前正在处理的所有合同.

接下来,您有以下内容:

Javascript和Solidity简介-第2部分:Solidity

这是您实际要编写代码的编辑器。默认情况下,Remix UI具有您现在可以忽略的投票智能合约。不需要进入这个.

之后,您将拥有:

Javascript和Solidity简介-第2部分:Solidity

这是程序日志.

您在编码时遇到的任何错误以及程序的所有输出将在此日志中详细说明.

在右侧,您有:

Javascript和Solidity简介-第2部分:Solidity

在右侧,您将拥有完成大部分工作的部分。默认情况下,它将位于“编译选项卡”上,但位于“运行选项卡”上,您将在其中执行大部分工作.

Javascript和Solidity简介-第2部分:Solidity

环境:您可以在三种环境中执行智能合约:JavaScript VM,注入的Web3和Web3 Provider.

帐户:您可以使用五个帐户地址作为该合同的所有者。每个地址都附有100个测试以太令牌.

Javascript和Solidity简介-第2部分:Solidity

气体极限:为执行此智能合约分配的总气体限制.

价值:您想为交易提供多少个以太币.

现在就足够了。让我们开始一些简单的基本程序.

实体数据类型

首先,让我们介绍您将要使用的数据类型。在计算机科学和计算机编程中,数据类型或简单类型是数据的分类,它告诉编译器或解释器程序员打算如何使用数据.

数据是整数,字符串还是数组?

编译器做出这些决定的方式是通过查看数据类型.

因此,首先,让我们检查一下 整数 可靠的数据类型:

  • 正常的整数声明为“ int”,它从-128到127
  • 无符号整数“ uint”,范围为0-255,不存储任何负值

接下来,我们有 布尔值 仅存储“ true”或“ false”的数据类型。要声明布尔值,可以这样做:bool a;

之后,你有 弦乐 字节数.

您可以像这样牢固地使用字符串:字符串名称。字符串以固定的值数组形式存储.

字节是一个字节数组,长度为1-32个字符。那么字符串和字节有什么区别?

Solidity文档说:

根据经验,将字节用于任意长度的原始字节数据,将字符串用于任意长度的字符串(UTF-8)数据。如果您可以将长度限制为一定数量的字节,请始终使用bytes1到bytes32中的一个,因为它们便宜得多.

接下来,我们有一个很酷的东西叫做“枚举”。枚举是在Solidity中创建用户定义类型的一种方法。这是您声明它们的方式:

枚举操作{删除,更新}

 因此,您如何在程序中使用它们?

动作myAction = Action.UPDATE;

您创建一个类型为Action的变量,这是我们在上面的示例中使用的枚举的名称。然后简单地给他们分配一个动作.

你可以 阅读Solidity文档 获得有关各种数据类型的更深入的知识.

基本程序

#1你好世界

实用性实测度^ 0.4.19;

//第1节

签订我的第一份合同{

公开问候

向公共所有者讲话;

事件GreetingChanged(字符串oldGreeting,字符串newGreeting);

//第2节

函数myfirstcontract(string _greeting){

问候= _greeting;

所有者= msg.sender;

}

//第3节

函数setGreeting(string _greeting){

require(owner == msg.sender);

GreetingChanged(greeting,_greeting);

问候= _greeting;

}

}

因此,我们将智能合约分为三个部分。让我们看一下每个部分,看看那里发生了什么.

第一节

//第1b节>

 

<b>实用性实效度^ 0.4.19; b>

&nbsp;

<b>签订我的第一合同{b>

<b>    b>

<b>    字符串公开问候; b>

<b>    向公共所有者致辞; b>

<b>    b>

<b>    事件GreetingChanged(字符串oldGreeting,字符串newGreeting); b>

“ pragma solidity ^ 0.4.19”表明我们使用的是0.4.19版本的Solidity。 “ ^”还确保我们的程序也将在更高版本上执行.

“ contract myfirstcontract”声明我们的合同,我们将其命名为“ myfirstcontract”.

之后,我们声明一个名为“ greeting”的字符串,该字符串将用于保存消息。此字符串是“公共”字符串。我们还声明了一个地址类型为“ owner”的公共变量,以保存合同所有者的地址.

使用“公共”变量的优点是它会自动获取分配给它们的“获取”函数。 getter函数有助于访问变量的值,而“ setter”函数则允许您修改值.

之后,我们有一个名为“ GreetingChanged”的事件。此事件可确保在问候语发生任何变化时,都会广播该变化.

第二节

//第1b节>

&nbsp;

<b>实用性实效度^ 0.4.19; b>

&nbsp;

<b>签订我的第一合同{b>

<b>    b>

<b>    字符串公开问候; b>

<b>    向公共所有者致辞; b>

<b>    b>

<b>    事件GreetingChanged(字符串oldGreeting,字符串newGreeting); b>

在本节中,我们将声明一个构造函数。您可能已经注意到,构造函数与合同具有相同的名称。构造函数的工作是在运行时初始化变量。构造函数将“ _greeting”作为参数,并使用该参数初始化“ greeting”。同时,将发送参数的人的地址保存在所有者中。由于构造函数仅在运行时开始执行,因此保存地址的人就是合同创建者.

第三节

//第3节

函数setGreeting(string _greeting){

require(owner == msg.sender);

GreetingChanged(greeting,_greeting);

问候= _greeting;

}

在第三部分中,我们将使用setter函数,该函数将帮助我们修改变量中保留的值。作为参数,如果需要修改,此函数将接受新的问候语.

所以,函数内部发生了什么?

我们想为程序引入一些访问控制。因此,我们正在检查进行修改的人是否是合同的所有者。稍后我们将看到,如果其他人尝试进行修改,则编译器将引发异常并返回错误.

因此,如果满足该条件,则将触发GreetingChanged事件,并且将“ greeting”的值更新为“ _greeting”.

好了,现在让我们编译程序。保存程序,然后在此处选择“ myfirstcontract”:

Javascript和Solidity简介-第2部分:Solidity

之后,单击“部署”以执行合同。当您这样做时,请注意日志中发生的情况.

Javascript和Solidity简介-第2部分:Solidity

你看到那条消息?

它表明执行成功。您还看到“调试”按钮旁边的向下箭头键吗?单击它,它将打开交易的详细信息:

Javascript和Solidity简介-第2部分:Solidity

状态:表明交易已成功

交易哈希:交易的唯一哈希。它显示交易ID.

合约地址:智能合约的地址。每当成功部署合同时,都会为其分配一个地址,该地址的行为类似于合同ID.

:我们选择的合同所有者的地址

:显示构造函数已生成变量.

气体:我们预先设定的气体上限

交易成本:将合同发送到区块链需要花费多少汽油.

执行费用:执行合同需要花费多少汽油.

杂凑:交易的哈希 .

输入:这是以太坊虚拟机实际读取的已编译的可靠性代码.

解码输入:通过参数传递给合同的输入.

日志:显示合同可能产生的任何事件.

价值:由于我们没有为该合约提供任何以太币,因此显示为0 wei.

好的,现在我们希望您将注意力集中在屏幕的右侧。你看到这个了吗?

Javascript和Solidity简介-第2部分:Solidity

在“帐户”字段旁边,您会看到该地址的以太网令牌少于100个。这表明以太坊被用来部署合同.

单击已部署合同下的选项卡,它将显示以下内容:

Javascript和Solidity简介-第2部分:Solidity

在此:

  • “ greeting”和“ owner”是由于变量被声明为“ public”而默认创建的getter函数.
  • “ setGreeting”是设置器功能,您可以在其中输入数据.

由于“ setGreeting”采用了字符串参数,因此必须在双引号中输入数据。像这样:

Javascript和Solidity简介-第2部分:Solidity

输入数据后,按“ setGreeting”按钮:

Javascript和Solidity简介-第2部分:Solidity

我们希望您关注两个领域:

解码输入:显示我们提供的输入字符串.

日志:创建一个事件,该事件表明“ greeting”的值已更改.

好吧,现在让我们单击吸气功能上的“问候”按钮:

Javascript和Solidity简介-第2部分:Solidity

它立即为您提供Greeting变量的值.

当您查看日志时,将看到以下内容:

Javascript和Solidity简介-第2部分:Solidity

看到“解码输出”字段,在那里您会看到“ Hello World”.

同样,只需单击“所有者”按钮:

Javascript和Solidity简介-第2部分:Solidity

它显示所有者地址的值。现在,当您检查日志时:

Javascript和Solidity简介-第2部分:Solidity

解码后的输出显示合同所有者的地址.

现在,让我们做些事情。让我们在“帐户”字段中选择其他地址:

Javascript和Solidity简介-第2部分:Solidity

更改地址时,尝试在setter函数中输入新字符串,您将在日志中收到以下消息:

Javascript和Solidity简介-第2部分:Solidity

出现此错误的原因是,这会使我们放入代码中的访问控制失败。记住这一行代码:

require(owner == msg.sender);

这样可以确保所有者以外的其他任何地址都不能更改合同中的数据.

#2姓名和年龄

//第1节

实用性实测度^ 0.4.19;

签订mysecondcontract {

字符串私人名称;

私人年龄

//第2节

函数setname(string newName){

名称= newName;

}

函数getName()返回(字符串){

返回名称;

}

//第3节

函数setAge(uint newAge){

年龄= newAge;

}

函数getAge()返回(uint){

返回年龄

}

}

第一节

实用性实测度^ 0.4.19;

签订mysecondcontract {

字符串私人名称;

私人年龄

我们已经宣布了一个名为“ mysecondcontract”的智能合约。这有两个私有变量。字符串称为“名称”,无符号整数(非负整数)称为“ age”.

第二节

函数setname(string newName){

名称= newName;

}

函数getName()返回(字符串){

返回名称;

}

在本节中,我们将使用name变量的setter和getter函数。第一部分是一个普通的setter函数,它带有一个参数来初始化name变量.

第二部分是一个getter函数,它可以帮助所有者访问“名称”变量.

第三节

函数setAge(uint newAge){

年龄= newAge;

}

函数getAge()返回(uint){

返回年龄

}

这部分定义了年龄的setter和getter函数.

让我们执行合同并将年龄设置为“ 28”。现在,日志如下所示:

Javascript和Solidity简介-第2部分:Solidity

如您所见,年龄反映在“解码后的输入”中.

现在,将名称设置为“ Max”.

现在,解码后的输入字段显示名称“ Max”.

现在,我们可以检查age的getter函数以查看输出:

Javascript和Solidity简介-第2部分:Solidity

输出字段显示年龄.

现在,对于名称的getter函数:

Javascript和Solidity简介-第2部分:Solidity

现在它显示解码的输出,即名称.

继承与扎实

继承是编程中最强大的工具之一。可靠地,它可以帮助您从较早的智能合约中衍生出一个智能合约。格式如下:

合同A {

——-

}

合同B是A {

——

}

关键字“ is”表示合同B正在继承合同A的价值。现在,合同A可以通过访问修饰符定义要与合同B共享的元素。 Solidity为您提供四个访问修饰符:

  • 私人的:元素不会被继承,外部元素也无法访问.
  • 上市:元素可以被外部元素继承并访问.
  • 内部的:该元素可以继承,但不能被外部元素访问
  • 外部的:该元素无法继承,但可以被外部元素访问.

好的,既然我们已经提到了所有这些,那么让我们对合同做些继承。我们将修改mysecondcontract代码.

实用性实测度^ 0.4.19;

//第1节

接口调节器{

函数checkValue(uint amount)返回(bool);

函数loan()返回(布尔);

}

#section 2

合同银行是监管机构{

私人价值;

功能库(单位金额){

价值=金额;

}

功能存款(单位金额){

值+ =金额;

}

函数取款(单位金额){

如果(checkValue(amount)){

值-=金额;

}

}

函数balance()返回(uint){

返回值

}

函数checkValue(uint数量)返回(布尔值){

返回值 >=金额;

}

函数loan()返回(布尔值){

返回值 > 0;

}

}

//第3节

我的第二个合同是银行{

字符串私人名称;

私人年龄

函数setname(string newName){

名称= newName;

}

函数getName()返回(字符串){

返回名称;

}

函数setAge(uint newAge){

年龄= newAge;

}

函数getAge()返回(uint){

返回年龄

}

}

第一节

让我们看一下相关代码:

接口调节器{

函数checkValue(uint amount)返回(bool);

函数loan()返回(布尔);

}

让我们看一下相关代码:

接口调节器{

函数checkValue(uint amount)返回(bool);

函数loan()返回(布尔);

}

我们声明的第一件事是接口。该界面可帮助您定义功能,而无需实际揭示它们在内部的工作方式。其内部机制将在其他合同中披露.

第二节

合同银行是监管机构{

私人价值;

功能库(单位金额){

价值=金额;

}

功能存款(单位金额){

值+ =金额;

}

函数取款(单位金额){

如果(checkValue(amount)){

值-=金额;

}

}

函数balance()返回(uint){

返回值

}

函数checkValue(uint数量)返回(布尔值){

返回值 >=金额;

}

函数loan()返回(布尔值){

返回值 > 0;

}

}

因此,我们声明了一个名为bank的合同,该合同正在从接口继承其值。我们要做的第一件事是声明一个构造函数,它将初始化变量值.

之后,我们有两个设置器功能,分别称为“提款”和“存款”,可帮助合同从用户帐户中提款和存款.

特别看一下撤回功能.

函数取款(单位金额){

如果(checkValue(amount)){

值-=金额;

}

在我们提款之前,该函数将调用它从接口继承的checkValue函数,以确保用户的帐户中是否有足够的值来提取资金.

在setter函数之后,我们有getter函数,该函数按顺序返回:

  • 用户帐户中的余额
  • 用户是否有足够的钱来取款.
  • 用户是否愿意贷款。为此,我们只是检查用户的余额是否为 > 0或不.

第三节

我的第二个合同是银行{

字符串私人名称;

私人年龄

函数setname(string newName){

名称= newName;

}

函数getName()返回(字符串){

返回名称;

}

函数setAge(uint newAge){

年龄= newAge;

}

函数getAge()返回(uint){

返回年龄

}

}

合同的这一部分与以前相同。唯一的区别是它是从银行合同继承财产.

固体进口和图书馆

接下来,我们要介绍重要的固体功能,您应该熟悉它们,导入和库。为此,我们将创建两个单独的合约文件,分别称为“ library.sol”和“ testLibrary.sol”.

我们的library.sol程序如下所示:

实用性实测度^ 0.4.19;

合同图书馆{

功能测试() {}

}

testLibrary看起来像这样:

实用性实测度^ 0.4.19;

进口 "浏览器/library.sol";

合同测试库是库{

}

testLibrary程序只是导入存储在以下位置的Libraries文件:browser / library.sol。默认情况下,所有Solidity程序都存储在浏览器文件夹中.

访问修饰符和后备功能

访问修饰符和后备功能是一些有趣的小工具,可用于为合同增添趣味。让我们从后备功能开始。查看以下代码:

实用性实测度^ 0.4.19;

合同testTransaction {

事件SenderLogger(地址);

事件ValueLogger(uint);

功能()应付款项{

SenderLogger(msg.sender);

ValueLogger(msg.value);

}

}

这是一个简单的智能合约,可让您提取交易明细。基本上,如果有人向该合约发送以太币,则该合约将提取:

  • 发件人地址
  • 他们发送的以太币数量.

备用功能就在这里:

 功能()应付款项{

SenderLogger(msg.sender);

ValueLogger(msg.value);

}

如您所见,该函数没有名称,并且只能在每个合约中放入一个后备函数。这个想法是使任何人都可以与合同取得联系并向其发送以太币令牌.

因此,让我们执行程序并查看一些数据。我们将部署合同。在“值”字段中放入1个以太币,然后按“备用”按钮.

Javascript和Solidity简介-第2部分:Solidity

因此,现在让我们检查一下日志.

Javascript和Solidity简介-第2部分:Solidity

值字段中表格的最后一个字段,该字段显示已发送到合约的以太币(以wei为单位).

好吧,现在让我们在程序中添加一些修饰符并进行更改.

实用性实测度^ 0.4.19;

合约交易{

事件SenderLogger(地址);

事件ValueLogger(uint);

解决私人拥有者;

修饰符isOwner {

require(owner == msg.sender);

_;

}

修饰符validValue {

断言(msg.value >= 1醚);

_;

}

函数Transaction(){

所有者= msg.sender;

}

函数()payable isOwner validValue {

SenderLogger(msg.sender);

ValueLogger(msg.value);

}

}

好的,因此此合同与前一个合同相同。我们仍然想提取交易明细。但是,我们添加了以下两个条件:

  • 只有合同所有者才能发送交易
  • 交易应至少为1个以太币

因此,让我们看一下修饰符,看看我们如何执行它:

修饰符isOwner {

       require(owner == msg.sender);

       _;

   }

所以,我们到底在做什么?

我们已经声明了一个修饰符,该修饰符基本上是一个自定义访问控制函数,该修饰符运行一个“ require”函数以确保只有所有者才能使用合同.

您还注意到“ _”吗??

这表明在执行access修饰符之后,需要保护其入口的功能也要运行.

让我们检查下一个修饰符:

修饰符validValue {

       断言(msg.value >= 1醚);

       _;

   }

这又是一个简单的修饰符,用于检查传递到合约中的值是否大于1以太.

好的,既然我们已经定义了这些修饰符,那么我们将如何在函数中利用它们呢?好吧,让我们检查一下:

函数()payable isOwner validValue {

       SenderLogger(msg.sender);

       ValueLogger(msg.value);

   }

立即查看我们的后备功能吗?我们已经在功能标头中添加了访问修饰符,以限制对其的访问。现在,让我们通过Remix运行合同,看看我们能得到什么.

让我们在值字段中添加一个以太币,看看我们得到了什么.

Javascript和Solidity简介-第2部分:Solidity

日志显示:

  • 发件人地址
  • 合约内的以太币价值

现在,如果我们:

  • 发送少于1个以太币
  • 从其他地址发送以太币

少于1个以太

我们在值字段中发送了0.2个以太币,程序立即给出一个错误:

Javascript和Solidity简介-第2部分:Solidity

来自其他地址

我们从其他地址发送了1个以太币。再一次,我们得到一个错误:

Javascript和Solidity简介-第2部分:Solidity

实体的结构和映射

在结束本指南之前,我们想让您熟悉在编码时要遇到的另外两个概念.

  • 结构体
  • 制图

结构是缺少方法的对象。他们只定义变量.

实体映射有点像哈希表,该哈希表实际上进行了初始化,因此每个潜在的键都存在。可以这样声明映射:

映射(A => B).

A =可以是除映射,数组,枚举,协定和结构之外的任何类型.

B =可以是任何类型(包括映射).

让我们执行一个包含以下两个功能的程序:

实用性实测度^ 0.4.19;

合同展示图{

//第1节

struct帐户{

平衡

}

帐户myAccount;

函数structFunc(){

myAccount.balance = 100;

}

//第2节

映射(地址=> 帐户)_accounts;

功能()应付{

_accounts [msg.sender] .balance + = msg.value;

}

函数getBalance()返回(uint){

返回_accounts [msg.sender] .balance;

}

}

第一节

因此,我们声明了一个名为Account的结构,该结构具有一个名为“ balance”的uint数据类型。然后,我们初始化了一个类型为Account的名为myAccount的变量,然后使用structFunc()函数将myAccount.balance的值分配为100.

第二节

通过使用mapping关键字,我们将地址映射到我们的Account结构并将其称为“ _accounts”.

然后,我们有一个备用功能,可以将用户提供的以太币添加到他们的余额中。然后,getBalance()函数将更新后的余额的值返回给用户.

让我们看一下实际情况.

我们将向智能合约发送10个以太币.

因此,使用后备功能,我们向该帐户发送了10个以太币,您可以在此处的日志中看到该帐户:

Javascript和Solidity简介-第2部分:Solidity

因此,如果我们现在获得了BaBalance,那么我们将得到:

Javascript和Solidity简介-第2部分:Solidity

注意“解码输出”字段,并注意余额如何反映为10 Ether.

Javascript和Solidity简介-第2部分:Solidity

现在,让我们通过后备功能向合约发送10个以太币,然后通过getBalance()再次检查余额.

如果您看到getBalance()字段,那么您会注意到余额反映了20个以太币.

结论

除了我们这里介绍的内容以外,坚固性还有很多其他内容。在不久的将来,我们将向您展示如何使用坚固性来创建自己的加密货币.

但是,现在,如果您想进一步教育自己,请注册我们的固心课程。我们拥有训练有素的老师,他们将指导您完成开发者的旅程.

您也可以退房 这些系列的视频 通过“坚固性”。他们有很棒的视频,这里使用的大多数代码都来自他们的gitHub页面.

这两篇文章的目的是向您介绍JavaScript和Solidity。我们希望您现在已经掌握了基础知识,可以进行更具挑战性的计划/合同.

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me