00:00
好,现在下面我们就继续来跟大家说一说刚才的智能合约,大家可以看到我们这个智能合约我们点部署啊,这里我跟大家再说一下啊,刚才我这边可能呃,WEB3连接ma的钱包的时候,大家默认这里环境是连接的injected web3对吧?所以它会去自动检测我们当前浏览器里边插入进来的WEB3实例,这个插入进来的WE3实例是个什么东西呢?就是我们mama干的。所以检测到了有ma mask,它就会用我们的ma mask的账号切换到这个,来,我来试验着部署一下,点了deploy之后,大家会发现下面我们的简单存储这个合约已经生成了,地址也已经有了,然后下面会看到有一个get data和一个set data,这里两个一个蓝色按钮,一个红色按钮,它代表什么意思呢?来给大家再解释一下,就是这里的红色按钮就代表。
01:09
我们这个操作是要发起交易,要去写数据,而蓝色按钮就代表我们这一个请求,就不要写数据,就只只读就可以了,所以大家可以看到里边直接把这个给我们列出来的,显示出来的,当然了,它其实判定的是什么呢?它其实判定的就是我们这里有没有定义,比方说像view啊。比方说像之后可能还会跟大家说像Q这样的类型,如果定义的话,他就一定是蓝色的,他认为你不会做操作,但假如你不定义,我们现在直接试一下吧,这个其实没什么啊,不过我这里好像没有,没有联网的话,可能会有点问题,我看看这个编译器,呃,应该编译器已经下载了,应该是没有问题的啊,大家看这里编译器只是报一个错,呃,报一个warning而已。
02:07
也没有报错,所以其实没什么问题啊,好,我在这里deploy一下,我先把这个先合起来啊。放到下边,诶,大家来看它的两个就全变成红色的了,所以这个remix其实就是它只是简单的判断了一下我们这个函数有没有定义,就是说让他只读。啊,所以我们还是用刚才这个,就这个只读的会会好一点,对我们的这个消耗内存会好一点。好,我们现在就看一下,大家set data的时候,看看是不是可以可以随便的set啊,我们直接去set一个123。这边显示已经交易成功,这个非常简单,大家一试就知道了,这边get没问题,123,那有些同学可能想要做实验的话,会瞎敲几个字符。
03:00
大家有做过吗?会怎么样?对,大家看这里其实就报错了。To,这个我们的合约点data error。为什么呢?呃,对,这个很正常嘛,我们这里定义的是U,我们是无符号整形,你直接给一串字符,这肯定是不行的,所以大家就注意这是强类型语言的特点,一定要注意我们给定所有数据的数据类型。好,这就是这个很简单,所以我们就不多说了,呃。上一节课的时候,大家不是有同学提出说,哎,那这个东西能不能返回两个。就是能不能返回两个参数呢?那当然是可以的,我们这里可以再加一点东西来看看啊呃,我这个先把这两个删掉。比方说我这里可以,呃,除了这里多说一句就是了,我们这里做的是对状态数据的操作,读和取,这是两个典型的操作,那我们还可以做什么呢?我们还可以不改数据。
04:11
也不读数据,几乎就跟我们自己的状态,状态变量是没关系的,不是几乎就是跟状态变量没关系。那比方说我们这里定义一个,我叫纯计算法,纯加。那我们要定义一个纯加,那那肯定就是里边要定义两个数了,对吧,In a u a b unit b,然后我们把它定义成public。Returns。我们先他的一个sum。UK上。
05:02
这里大家看到我还可以在返回值,返回值呃,返回的类型后面加一个变量,这代表什么呢?这就相当于我们可以定义返回的这个数据,它到底这个变量名称叫什么,也就是说调用他的人或者外部的账户,或者是调用他的合约是可以拿到这个变量名的,也就是说我们可以定义一些有意义的东西在里面,对吧?所以像我们这里定义了一个some跟够一模一样是吧?啊,那大家应该这个都不用讲了是吧?A加B。所以大家可以看到,我们这里有一个简单的方式,就可以把它定义一个Q。这样的话就代表这是一个纯计算的函数。哦,又看不到了是吧。好。
06:02
这个关键字的意思其实就代表这个函数是什么,它的这个状态是什么意思呢?就是说它既不读也不写,简单说就是这样。它就是做了一个纯计算,好,那我们把它deploy一下。好,我们可以看到多了一个这个A的一个属性,那我这里随便出两个数吧,三和43。学艾特一下,大家可以看到返回的时候,它就多了一个SUM46,它是连这一个,它的返回的变量名称和这个数数据一起返回的,这就是这样的一个定义。那大家刚才不是说它是不是可以返回多个吗?那比方说我再返回一个,比方说这个叫。A吧。因为我对go是不是很熟悉,大家如果学过够了的话,那应该是如果这个跟go里面一样的话,那应该很熟悉,对吧,这就这么写,对,我们如果要返回两个变量的时候,A加B放前面,A放后面。
07:13
逗号分格,小括号括起来,然后在前面returns里边,我们去把some放在第一个后面这个假如说我们说原始的A,那么我们就加一个orange a。我们让一下。好,现在我们还是随便给一个数。两个大一点的数,大家可以看到加起来是5490,原始的A是3245。所以大家可以看到,前面大家可能一直看到它一直回来之后是有一个零冒号,这什么意思呢?就是因为它默认返回的参数是一个数组,所以每一次都有一个零,这是代表它就只有一个,那如果说我们有两个返回的时候,它就是零一都在这里列出。
08:01
大家熟悉够的话呢,肯定大家知道,就我这里能不能给一个U的A呢。就假如说我要返回A嘛,用的A可以吗。大家看这里已经给你报错了,对吧。他说的是什么?Identifier already declared,对,那不能重复定义,因为我们这里本身这个传入参数定义了A,我们返回的参数肯定就不能定义A了,对吧?那我们定义一个不同的变量名就可以了。好,这就是我们这一部分啊,呃,那接下来我觉得还是想让大家多做一点,就是练习,那我们这样吧,大家把这个删掉,或者是自己保存,自己再另外建立一个建,建立一个新的合约,我们也简单一点,就叫car,想建立一个比方说,呃,就是作为一个汽车的一个这样的一个操作,怎么样的一个操作呢?就是我们可以给这个汽车指定它的名字和它的价格。
09:11
给他两个参数。大家可以想想这个东西应该怎么实现,当然可能会涉及到我们没有用过的数据类型啊,我这里可以其实告诉大家就是这里边是有string,大家直接可以打一下,看看它有没有这个关键字,对吧。是有这个关键词的。我们如果想要的数据类型,可以用string来实现。好,我们还是来。Solid,呃,我们还是要0.4.22啊。好,现在我们建一个contract,我们名字就叫car吧,我们说在这一个合约里边,我们要给它定义两个状态变量,一个叫做它的品牌,一个叫做它的价格,对吧,那这两个状态变量大家肯定就首先就想到了它数据类型,诶我没有开这个。
10:11
大家可能就想到了,它的数据类型肯定是不一样的,因为品牌的话,这个应该就是一个字符串嘛,所以我们在这里先定义一个品牌string在跟很多编程语言都一样啊,就是所以里面也有string这个关键词,它就是一个字符串,好那么我们比方说品牌应该叫叫什么叫叫brand吧。定义一个品牌,然后再定义一个价格,那价格应该是一个数了啊,所以我们这个给一个是可以的price,嗯,那可以对,当然就是我们可以去定义这个就是浮点型的,甚至可以就是定义这个浮点型,那个改变长度的这些这些数字都是可以的,之后我们就是详细介绍数据类型的时候,跟大家说其他的一些类型,好,这一个有price,就是一个整形啊,那接下来我们还说。
11:17
呃,我可能看一下这个。哪里写错了吗?大家看的很细啊,对,他一直报编辑错误,我也没有注意好,那我们说在这两个参数里边,我们会需要去把它们也是做一个set,做一个get,那其实这个东西跟我们刚才做的没什么区别,是吧,Function set brand。哈,然后就可以set了,当然这个brand就会等于我们传进来的一个street new brand。
12:09
跟刚才的实现几乎没有什么区别,是吧,Get brand,所以我很快的过啊,Public view returns。那同样了,如果说要去设置它的price的话,那是一样的啊,这个可能有点浪费时间了,给大家在写这些,诶,它的属性是一定是私有,呃,对这个还没有没有说到,就是这里它的属性是私有的,当然我们也可以给它变成公有的属性,公有的话它就排面它不当,呃,不用不需要,这个它并不敏感,但是会改变一些别的东西,那我们这里这样吧。
13:03
我这里只只先set price啊。Price应该是new。Public。Price等于new price,好,我就不设它的get price的这个属性,但是呢,我可以在这里来一个public price。咱们看看加了public price之后跟brand它会有什么区别,好,我们在这里一下。好,已经生成了这个car的合约,诶,我们看一下它里边的函数。Set brand和set price这两个做了这个赋值的操作,改变状态变量,所以它是红色的,都放在这儿了,Get brand也有,下面大家看到多了一个price。
14:01
就是这就说明当我们定义了一个public类型的状态变量的时候,其实我们是可以在外部直接访问到它的,所以其实在solidity里边,我们定义的public类型的状态变量,Solidity会直接给它生成一个相当于get。方法就是生成一个get,相当于是这样的,所以刚才这一就是我们定义了public这一,这一步呢,就相当于是我们写了一个function price。然后public view returns。就这样。呃,当当然这就是price了啊,就相当于我们都写了一个这个,所以嗯,什么就是保护是protect,呃,没有protect的这种类型,但是它是会有,就是像internal这样的这样的类型。
15:14
好OK,呃,现在我们就就先不看这个了啊,我们主要说这个想要说的是什么呢?是大家看一下这里的这个这个编译的状况啊。编译的,这里其实是有了两个warning的。但是这个warning跟我们平炒到的黄色的那个warning还不一样,黄色的那个主要是属于就是我们语法习惯啊,书写就是编译过程当中的一个warning,它这个蓝色深蓝色的warning,它说的是什么呢?Sta static analysis。就是他的分析报了一个网瘾,我们点开看一下。大家可以看到啊,他说GA requirement function get brand,就是说这个gas的需求量。
16:09
会比较大,有可能会比较大,对吧,甚至有可能无限,这是为什么呢?为什么我们去get一个brand,它就有可能会无限呢?因为字不串的话很大,对对对,非常非常对,非常对对就是就是这个问题是比如说我丢一篇文章过去的话,因为你这样子的话,你拿回来的话就太大,对对非常好,就是就是这样的问题,就是因为我们知道字符串这里是不限长度的,那假如说我们这里传的非常非常大,非常非常长,那一定这个过程是非常盖的,对吧?所以这里大家其实是能能直接的直观的感受到这一点,但是我们这个先,我们先看一下运行结果对不对啊。比方说我们这个车,我们就叫一个宝马吧,BMW,呃,首先我们先get一下,看看它,它是什么,它什么都没有对吧?一开始什么都没有PRICE0,大家可以看到这个不赋值的话,它一开始就是零。
17:13
我们先set一下。诶,大家可以看到这里报错了errorcoding arguments,所以我们给的参数错了对吧。诶,那这个是得得什么意思呢。嗯,对,因为这是个string,所以我们一定要把它引起来去给。所以这就是这就是静态类型,它对数据类型的要求非常高,所以大家一定要注意这些点,就是有可能我们会遇到各种各样的问题,好,现在这个打了对号就应该是成功了,我们get看一下BMW宝马车已经上架了,来我们给个就就10万的数字吧,尽管这可能这这在我们里边有可能是伪的意思,但是在在这里边的话,这我们自己定义,那就不是伪了,对吧,所以我们就直接给一个10万。
18:06
诶,好,我们刚才没点是吧,Set set price好成功,然后我们get一下是吧,没有问题,好,这是刚才我们说的这个注意。String这个数据类型,那刚才我们说了,那string这个数据类型,它会它会报警的,这个有可能会有问题的,那我们怎么办呢。所以为了如果说大家想要改进这个性能的话,如果说我们只是实现这个功能的话,这个已经足够了,对吧?如果大家想要改进这个功能,我们怎么做呢?我们可以把这个string改成别的东西,比方说改成别的字符类型,比如说在里边提供了一个叫做bit的数据练习。比方说这里有三二。那三二是个什么东西呢?直观理解就是32个字节的一个字符数。呃,所以这里改了,我们当然这里的返回值也要改,对吧,三二。
19:07
这里也要改盖三二,所以大家可以看我现在编译的话就没有任何的光了,所以这个BEST32是固定,相当于是固定了它的长度,所以这个长度是受限可控的,在这个过程当中,它就会相对来讲就会比较安全一点,不会消耗到无无限的GA。呃,那大家可能就会说了,那如果有些时候我就是这个长度不能固定的,呃,那当然了,所以所以string也是能用的,并不是说string不能用,只不过对于我们来讲,可能像汽车品牌这个东西,我们肯定没必要给他,给他无限的这种空间,让他有可能去去去有人利用这个来坑我,所以对于这种事情我们肯定就用这样的方式来来设定,到传值的时候不知道怎么传的是吧,对,就是这里可能会有问题,呃,这里需要跟大家说的一下就是啊,我们在这里先先试一下吧,我们还是传个BMW试一下,或者我们换个车吧,奥迪吧。
20:13
诶,大家看这边就就直接就报错了,对吧,他说inval的32VALUE,所以大家可以看到它直接就检测出来我们这个type还是string,也就是说我们用双引号引的引住的字符串。默认就是string类型,那BA32它到底是个什么类型呢?它其实是一个16进制字符的类型。所以在这个地方,咱们就不能不能这么去去输参数,但是咱们可以用0X这种这种打头的16进制的这种数据去输参数,这样的话就会成功。但是当然了,这样的话可能就没什么实际意义,对吧,我们get get brand,然后发现这个BY3232位是一个这样的一个东西。
21:03
那我们平常用的时候,那那这玩意儿是怎么用呢?呃,这个东西就是我们肯定要用别的工具去做这个,呃,String在本身扫里边存储的时候是用UTF8的。就是字符集来做存储的,所以它它是来来用UTF8编码的啊,所以我们在去平常应用的时候,假如说考虑性能一定要用BEST32,那我们在外部调用的时候,最好就要做由UTF8到对到16进制的编码转换,比方说这里举个例子啊,但这个编码转换也不难。那我这里是退出来了,没有没有起值的外WEB3是吧,好,那我们还是进一下,进到我们的自己的链里面去MY。
22:09
这个我不需要去连它,所以我们就直接起一个pencil色就可以了啊好,现在大家看一下WEB3里边最下边的工具类其实是有很多的,大家可以看到啊,呃,From us from u tf8 from decim from way啊,但这这我们知道了啊,下面大家可以看到to ask To Big number to DEC tos to u吧。所以我们可以调用什么呢?比方说我们要想知道奥迪这个车标,它到底变成这个16进制的has,到底是个什么东西呢?我们可以to has,我们输一个奥迪。
23:01
大家可以看到,这是它的汉值。所以我们在那边去存的时候呢,就应该是存这对吧。我所以我们这这其实就相当于模拟我们的一个APP的应用了,APP应用的时候交互怎么交互呢?我们在这边把用户输进来的这个字符UR编码调一下to has,先转成这个16进制,然后我们把16进制传给我们的合约。然后当然了,合约这边读出来也是16进制了,那我们这边我们的APP这边拿到这样的值之后呢,就还需要在这边再转成UTF吧,比如说web3.toutf吧,呃,这个我们先看一下,我忘记这个要不要加引号,这个好像是要加引号的。哦,果然报错了。
24:03
好,我们把它拿过来,这他后面都补了零的,我看是不是,诶是一样,所以后面补零是没关系的。呃,这就是如果我们要是自己去写应用,跟用户去交互的话,我们肯定不能让用户输入这个16进制值,所以说我们自己要做这个转换的过程,好这是这一部分内容,呃,然后我们还想在上面再加一点内容啊,就大家可能会想到我在初始构建一个car这个类型的时候,可能我会想要他一开始其实我就设定应该有初始值的。是不是就如如果说他是我们的,嗯。好。就如果说它是我们真正用户调用我们的接口来创建的一个卡的话,就如果是用户调用的时候,我们才会构建这样一个合约实例的话,那他一定是有初始值的,对吧?后面的set get是访问了set,那只是有可能数据想要去更改,更改的时候才会去set,正常来讲一般数据可能都会有初始值,初始值怎么去付呢?那当然就应该是在他创建的时候就去付,在solid里边我们用什么样的方式去创,创建的时候就给它付初始值,这里边对constructor。
25:32
这个也是跟别的编程语言应该很像,对吧,PHP啊,所以这个是借鉴了很多很多这个前端或者是别的一些语言,Constructor。呃,这个就包括JS的很多框架里边也都有constructor之类的东西,对吧?呃,比方说这里,如果我们想要去把一开始就就把它的这个品牌和这个价格都传进来的话,那我们就可以一开我们这品牌,还不要这么别扭了啊,我们先不管这个,还是改成STEM吧。
26:04
还是舒服一点好。两个没有别处了吧,这里是。好,那么我们一开始就要传入一个比方说叫in brand,就是它的初始品牌,还有就是unit,我们可以传入一个in price,就是价格也可以调整。那这个传入进来之后会起到什么效果呢?给我们的变量直接去复制brand,默认的是这个brand等于in brand price,那就等于in price。好,当然了,我们前面这个constructor也应该给他public。
27:02
因为我们在外面要去传职的,对吧。好,大家可以看到,这就是我们加入了一个很constructor这样的东西去做这样的一件事情,Construct该,呃,对,是em,就是在我们创建这样一个合约实例的时候,EVM就会自动去先调用这个construct。所以这个东西就是在合约创建的时候,不需要有人调就直接可以生效的一个东西。好,我们现在来,然后这里是第三行一问题不是第是第16号,假设我现在传的一个价格,比如说我,我希望他,但是假设你一过了,我说我我就应该要对那一个new禁止死,这时候我的个是不是就不就是我后面。
28:00
的get,然你是说set的时候想判定他是否符合你的条件是吧,你要set的话肯定不会是view嘛,对吧。嗯,好,那么我们来看一下这个deploy之后的一个状态。诶,这个。好像没有,应该是编译的吧。好,我们看一下,现在我们看一下get,怎么里面什么东西都没有呢。因为我们没付出值对吧,咱们就没有提供这个参数,他当然就不知道那付出值应该在什么地方,付出值呢?大家可以看到这个constructor尽管是public类型,但这里我们是访问不了。
29:07
那我们就不就不知道什么地方不出值了是不是。大家觉得应该是什么时候,对deploy的时候,大家看deploy后面其实是有这个参数提示的,你可以传入string类型的in brand和UNIT256,大家看unit就是UNIT256对吧类型的price,所以我们刚才这个就没有部署给到数值,我们可以在这里给到,呃,再再想一个车,还能想到什么车?奔驰啊对奔驰,然后好给他个20万吧,太便宜了是吧,都好我们一下。现在部署成功之后,我们看一下他的brand是奔驰。它的price是20万,所以这是这样一个过程,好大家可以在在就是花一点时间把这个constructor实现一下,然后自己试一试,应该也简单是不是,我一边敲大家都已经做完了,对,很简单,对吧?在这里我需要说一句的是,为什么我们上面要求是。
30:18
就是4.22呢,我这里没有网啊,所以说我不不敢换,随便换这个编译器,大家如果网好的话,大家可以尝试把这个版本限制改低,比方说0.4.0,然后把编译器的版版本改到一个比较低的版本,可以看一下。大家可以试一试,那个时候这个constructor这一行就会报贬编译错误,为什么呢?因为constructor就是在0.4.22之后才引入的一个一个,呃,保留字关键字。在之前大家如果在网上去找一些学习资料,或者说看一些别人的教教程的话,可能会看到这样的写法,就是他没有constructor,它怎么写呢?他会写function car,对,他会这么写。所以这可能也是一些编程语言跟另外一些编程语言习惯的一种写法,对吧?就是在自己的类里边和类名相同的一个函数,就是自己的构造函数。
31:24
这个应该大家也会比较熟悉这种写法啊,就这两种写法其实都可以,但是大家看到如果我现在的编译器版本比较高,我用这种写法的时候,他就会泡一个warning,他说呃,DeFinning constructors as functions with the same name,就是用这个同样名字,跟我们的这个合约名字相同的名字,定义一个一个函数,定义我们的构造函数,这个呢,它是depreed,那就是要被废弃了,要被废用了,所以说就是他后面说use constructor。
32:05
所以说大家现在的编程习习惯还是最好是就是写成constructor会比较好一点,但是大家如果要是看一些别的,呃,一些教材或者怎么样,大家看到那种写法也不要觉得奇怪,它只是一些就是之前的这种历史版本的地方就可PP一模一样是吧?PHP以前也是那种写法是吗?比如说开始方身,后来他就增加了一个东西叫做魔术方法,有种叫做CT,对,Druct,对,所以前面我们也说了,就是在这个car里边是可以有那个self druct。所以那个就是一个撕毁方法,好,这个我们就先不多说了,这个就是作为我们,呃,算是对这个的一个直观的了解,直观的印象,我们先有了这其实到目前为止一个很简单的合约,这尽管也很简单,但是我们其实能做的事情已经很多了。
33:06
至少我们可以自己定义一些计算的,就是工具类,对吧,工具方法我们可以让它算一个什么东西,另外我们也可以存储一些东西,然后把它拿出来,那大家有计算有存储,那其实我们能做的事情已经很多了,对吧?而且我们也知道它的规范,就是初始化的时候构造函数怎么去做。好,这一部分我们先讲到这里。
我来说两句