00:00
好,接下来我们再看啊,就是地址类型,它比较特别的一点就是为什么它又跟它本质就是一个24节的一个一个值。或者说我们说它可以直接转换成U160,那为什么它还有那么多奇奇怪怪的属性呢?那就是因为它还不仅仅是这么一个值。它和排可以看成一个大的一个对象,一个结构,所以它自己是有很多的成员变量的。大家看到它有哪些成员变量呢?首先最直接的就是address,一个address可以点balance。有这样的一个balance成员变量。那这个很简单,就是能够直接获取到这个地址的以太余额,以尾为单位。另外就是我们经常用到的,可以从一个地址直接往出转币。那就是它有点transfer,这个正可能不应该叫成员变量,应该叫成员函数了,对吧?这是一个函数,它的后面的参数类型是给定一个256的amount,我们要转几个B,把这个写进去,所以大家可以看到这个用法就是前面是一个address,当然0.5之后的话,那就是必须是一个address payable的类型,然后一个address payable类型,点transport。
01:26
后面括号加上以态数列,它的含义是说从我们前面的这个地址里面往出转。那大家还记得我们当时转的时候,其实后边是还要加receiver的,对吧?呃,就是你到底是转给谁,其实是要是要是要有这个参数的,所以这里面没有详细的列,但是我们之前用过的话,其实大家应该记得我们试一下,我们在这里看到,呃呃,比方说我们现在如果要是获取。
02:00
自己的地址怎么获取呢?对,是可以用this啊,对,尽管我们平常调用它里面的成员变量的时候,状态变量的时候不会用this点去去调用,但是如果说获取地址的时候可以直接用address this来表示这个地址,那我们就直接可以address this.balance大家可以看到,如果要是就是仅仅是这样的话,大家可以看到是有问题的啊。看到它提示的这个语法错误是什么?Unexpected fire。高哦,他说这个这个这个用法不对啊,就是不能用这个address后面直接直接跟this的方式,这个可能我们编辑器版本比较高了,在以前的版本里面是是可以这么用的,那现在我们要用它的这个balance怎么样去用的看应该是有这个这风法。
03:06
呃。直接看肯定是不行的,我们在上面去定义一个。没有balance属性是吗?哦对,大家可以看到,因为我们在这一个这个。合约里边它其实是没有回退函数的,没有回退函数的话,那应该是不能直接去拿到它的balance,对吧?对,所以在这里的话,我们应该还是得就是它是一个table类型才可以我们另外建一个contract。比方说我们叫。呃。我们在这里,假如说我们给他一个,还是给他一个一个变量啊,大家就是看不到是吧。
04:12
假如说我们这里就是别的一个合约,要调用我们的这个car这个合约的话,我们可以直接定义一个啊,当然这个就是就是这个语法类型跟我们之前的这种这种写法其实都是类似的,我们可以直接去拗一个一个,呃,这样的写法应该是。Balance,我们试一下看看可不可以啊,先把这个注掉啊,果然还是不可以,那看来现在是就是不允许这个写法的啊。呃,觉得这个应该放在函数里面,不能直接去调是吧,对这个。
05:03
写在一个方式里面。呃,这样吧,我们就直接把它放在回归函数里面好了。你看这里。哦,就是这个hard构造函数里面是有东西的,对吧。比如说我们给他一个指定的值,这个他就不会报错了。然后我们把刚才的这一句放在里面,所以大家可以看到对刚才我又犯了这个错误啊,就是经常就是我们在测试的时候不注意,不把它放在方式里面,直接在外部去定义,但因为大家看到外部的话,其实全部都是它的成员变量定义,对吧,就是我们上面都是它的状态变量。
06:07
下面都是它的。方法函数,所以在这里边我们是不可能直接去做调用的,要调用的话,我们只有在方法里面去调用,或者在外部去卡点什么去调用,所以呃,正常的情况我们肯定不能直接在下面它它直接去我们前面这么写是没问题的,我们定义定义的只是一个状态变量,但是这个时候我们要做调用肯定就会有问题了啊,但大大家不要犯我这种错误啊,我确实经常犯这个错误,所以大家可以看到就是它的用法很简单,就是直接address后面去。加入我们一个合约的类型,也可以是比方说this,也可以拿到自己的这个balance,当然了,在这里大家可以看到那个它不是payable类型,其实也是可以这么写的,但是可能调用的时候就会有问题啊,这个大家可以下去自己做一些尝试啊,就是自己去挑一些呃,自己想要去证明的一些点,对吧,他这个数据类型到底怎么用的,他会有什么样的行为,大家可以随时去敲一些这样的东西。
07:14
好,我们这个就。就先说到这里,然后呃,Transfer这个函数是我们经常要用到的一个一个方法了,我们前面的水龙头合约大家还记得对吧,我们就是直接调用了穿。看一下水龙头还在吧,嗯,大家可以看到我们直接就是messages.sender因为我们知道messages send本身就是一个地址类型,对吧?所以我们这里不需要再做转换了,它直接点transfer,我们看到后面加一个amount就把它直接就发出来了,所以大家可以看到就是它的这个类型,哦,我前面说错了啊,前这个不应该再加receiver了,对吧。因为我们本身的这个前面调用的地址就是它的。
08:01
诶,大家大家大家这个是知道的吧,就是我们如果调一个transfer方法的话,是前面这个地址到底是从这个地址发还是这个地址接收。对,那是谁发。合约发。大家想一下。我们当时的水龙头合约这一句me.transfer amount,我们指的是把这个从谁给到谁。从我自己是给水龙头是吗?来再再回想一下,我们调这个withdraw的时候,我们是想从水龙头拿拿钱,还是说给给他转钱啊,拿钱呢,应该是水龙头给我们对吧?对对对,这个大家注意啊,就是因为它的这个习惯,可能跟咱们平常的那个用法不太一样,因为咱们平常的用法感觉好像你既然是transfer嘛,甚至就是它后面大家看到还有一个sand sand可以认为是transfer的,这个就是低级版本啊,就是它底层的版本,那大家想我一个地址,然后点send.transfer我想的肯定就是我这个地址去给别人发嘛,对吧,但其实不是啊,这也是三里边这个地址类型很很奇怪,就是容易让人搞搞乱的一点,就是它的这个地址点transfer。
09:34
指的是要给前面这个地址发,所以大家看到我们这里的message点三点transfer是指的是谁调用了这一个方法就给谁发。所以我们当时点一下只能给我们发一个币,对吧,是这样的一个一个动作,所以那它的发送者是谁呢?就是当前这个合约。对吧,所以前面就是说这个就是合约自己发的同学说的是对的啊,这个理解的非常到位,呃,所以这里就是大家注意一下这个点transfer和点散这两个方法,它我们在用的时候,大家可能直接拿来就用了,但是一定要搞清楚到底是谁给谁发,别到时候就是我们本来是要给别人发币,结果变成了就是就是想要,就是我们本来是想要从别人那里拿币,结果变成了给别人发币,那我们的钱就确实就是很容易的就都都发出去了,对吧,就是合约的这个逻辑上一定要考量清楚。
10:37
那下面就是散的这个方法,散的方法呢,它其实大家看描述跟上面的transfer完全一样,呃,不是完全一样就基本一样,差别在哪里呢?对,差别在失败的时候不一样。Transfer失败的时候抛出异常回退。而散的方法失败的时候。
11:01
它是返回false。所以在我们的交易里边,如果要是用了send方法的话,默认其实它是执行成功的。所以大家要注意啊,就是因为它没有异常。整个我们如果要是用那个异常捕获机制去去抓他的话,是抓不到的,因为它是正常返回的,只不过返回一个false,呃,所以这也就是说一般给大家推荐的时候都用transfer,不要用更底层的send,如果用了send的话,那我们还得去抓它的返回,去判断false,再去做异常处理。大家如果愿意自己去做更底层的事情,可以这么去用,但是就是不推荐,肯定不推荐大家这么去用,呃,另外一个就是说这个transfer方法和send方法呢,它是是固定的发送2300GA。就是只要调一下这个transfer,就是2300,这个是不能调的。
12:01
固定的一个就是best的消耗量,下面还有几个底层函数啊,就是大家可以看到一个叫做空。一个叫delegate core,一个叫static Co,所以看起来都是Co,对吧,那最根本的就是这个core函数,这个是一个什么东西呢?它是一个就是在扫里边非常底层的一个一个函数。它的作用是就是函数调用,就跟它的直观的这个概念一样,它的它的。意思就是说我直接去靠后面跟的参数,大家看到是一个BY。Memory里面的一段BY。所以它就是直接要靠后面的这一部分内容,用BY的形式,用就是二进制的形式去靠。呃,它就是非常底层的东西了,呃,我们一般情况大家可能用不到,但是如果要是看到别人的合约里面这么写的话,呃,大家知道他是要要做什么样的事情啊,那同样他跟上面的send一样,也是失败的时候不会抛异常,直接返回一个false,然后它会发送掉所有可用的干,就是它,它默认去。
13:21
我们在call另外一个方法的时候,一般情况就会调用到另外一个合约嘛,所以他会把剩下的盖全部都发过去。这是跟前面的transfer和send不一样的地方,Transfer send发的时候,不管现在我还剩下多少盖,我固定就发两千三啊,当然如果要是两千三都不够的话,那肯定就直接就对吧,好,GA抛异常了,那靠的话是你如果默认不设置,那就剩下的盖全发过去,因为他不知道你要靠什么样的方法嘛,有可能很耗guess。所以下面的delegate call呢,那顾名思义,它其实就是说,就是我们可以去做一个代理的调用,那代理调用是什么意思呢?其实简单就是说我可以,我们前面其实说过代理调用这个概念的,就是说我可以。
14:14
不是把我自己的地址,合约地址作为我调用的这个环境里面的MESSAGE3。对吧,而是用我这边本来获取到的那个mes center,就是原始调用者的mesenger send和mesger me,所以这样的一种调用方式叫做代理调用。那这个特性呢,其实它是从这个第二个以太坊的大版本,就是homete这个版本才开始引入的,所以就是它相当于也是相对比较新的一个用法啊,另外还有一个就是static static call更新,它是第三阶段拜占停之后才引用的,顾名思义它是什么意思呢?它是一个静态调用,也就是说它基本上跟car是一样的。
15:03
特点就是说你必须是静态的,你调用别人方法的过程当中没有任何的状态改变。就是如果要是状态改变了,那直接就返回false,直接就报错了,所以呃,这是就是这几个很底层的函数啊,那就是在那个比较老的版本之前,就是在homete之前呢,还有另外一个很很底层的函数啊,就是还有一个叫做应该是叫做。靠扣还有一个,大家如果要是见一些比较老的技术文章,他去写这些,就是大家怎么怎么用这些东西的时候,有时候还会看到靠扣也也不要惊讶,他就是比较老版本的一个,就是想要实现delicate call,或者是别的一些这个用法的一个一个机制而已。我们这里只是给大家做介绍,推荐大家使用,因为它特别特别的底层,我们这里给大家介绍完了之后呢,就是只是当成最后一招来用,假如说最后我实在没别的方法去调用另外一个函数了,我实在就是想不到,就是它各种各样的限制,我我不知道怎么去做了,那最后一招可能大家可以尝试用用这种非常底层的方法,它是任何任何函数都可以去调用的,任何东西都可以去调,这就有点像我们在C或者其他一些允许但直接去操作内存的一些语言里边就是大招一样,对吧,直接去去操作内存里面的东西,直接把它改了啊,所以呃,这这个就是大家为什么说不要让大家随便去靠别的这个函数呢?是因为别人的函数,你如果要是靠别人的函数。
16:54
这一段逻辑的控制权就会全部放在别人的函数里面,你不知道别人到底会做什么事情,所以有可能他会返回来改你的状态,有可能他会把你这边的逻辑直接全搞乱,所以说这个我们一定要去谨慎使用啊,还是用比较上层的函数也会好一点好接下来其实这里已经就是给大家列了这个成员地址变量,呃,地址的成员变量的用法,其实前面我们都已经试过一下了,对吧。
17:27
大家看这个balance和transfer啊,呃,最简单的用法就是address payable,一个变量定义一个变量,然后后面定义的时候呢,可以把这个值给它传进去,比方说这个值我们直接给的也是一个X值啊,0X打头的,呃,零当然0X123,这个其实不是一个合法的一个以太坊的地址啊,以太坊地址当然应该是呃,20个字节160位了,嗯,那我们这里就先先不管这些啊,就是只是一个例子,Address后面一个my address呢,它直接指定的就是合约地址,大家看就是刚才我们address this的这种用法。
18:06
那在转账的时候呢,大家看就直接可以x.balance小于10MY address.balance大于等于十,可以去直接调用它的balance成员变量去做判断,然后下面如果要转转账的时候,x.TRANSFER10这个表示什么意思?x.TRANSFER10给给谁发,给X发,发多少十尾对吧?对正常的这个单位都是尾,所以大家注意,就是我们正常的语义理解,确实这个有点反反我们直觉啊,这个正常的感觉应该是x.transfer或者说你X点三,那那不就应该是他去发吗?那可是这个股市啊,这个是。谁掉穿粉就给谁发。是这样。好,那下面啊,我们还是说一下这一句啊,呃,Send是transfer的低级版本了,就是如果执行失败,它返回的是false,不会不会异常啊,另外还有一个就是call call本身这个底层函数,它非常的强大,几乎什么事情都能做,呃,大家可以看一下,我们前面不是transport和send吗?靠,能不能做这件事情呢?能。
19:22
大家可以看这个car怎么去做这样的一件事情,去做我们所谓的transfer的。工作。大家可以看到啊,中间的这个盖和value先不看,如果不看这两样的话,它其实就是呃,Name的一个引用,也就是说我们的一个地址,然后点靠。后面的参数是这么一堆,下面的这么一堆。大家可以看到啊,就是你看它是怎么做的,是abi.in code in code with,呃,Signature,就是是要用签名去做编码,对吧,然后里边一个register,一个string,然后后面my name去做签名,所以大家可以看到,就是它里边其实是要用到很底层的信息,然后我们把签名编码之后的东西。
20:09
放到它后边,所以我们知道它是一个二进制的一个,一个就是BY,对吧,它要传进去的是BY,不是我们简单的一个东西,所以这个东西要调用,其实也不好调用啊,我们要知道很多底层的这种操作才行,另外大家看就是它还可以直接指定转多少钱。怎么指定呢?它可以加修饰器。看到这种很很奇怪的,这种调用方法是靠后面点guess。后边里边100万,那就指定的是GA price是100万,然后。呃,这个应该不是啊,这个GA后面应该是GA GA limit的啊,不是GA price我说错了,然后点value大家可以看到,就是直接我可以后面给1EER eer大家看伊ER是可以直接写的,是关键字对吧,大家其实在我们这个里边如果说。
21:06
大家平常这么写,如果要是写一的话,那transfer就是一尾,对吧?对,大家可以直接这么写,这是这是合法的啊,合法的字符,所以。地址的成员变量这块其实主要就是transfer和balance,大家平常用的时候只用这两个就可以,别的我们只做了解,很底层尽量不要用。好,接下来我们看一下字符数组,字符数组这一部分呢,就是我们所说的,它是一个定长的字符数组,呃,不不是啊,就是说它分为两类,就是一类是定长的字符数组,一类是变长的字符数组。那定长的字符数组呢,它就属于我们前面讲到的直类型了,前面我们已经说了它BA1BA2,一直到BASE32对吧,BASE32,那它就代表一个32个字节的一个。
22:03
BY的序列,也就是说我们所说的bitt的一个数据啊,这个是比较简单的啊,它呢会有一个点lengths的属性。这大家注意一下,数组里边的点LAS还是比较重要的一个属性,稍后我们会再讲到,就是点LAS的一些操作,它返回的就是当前数字的长度,也就是说我们如果定义了一个BY32的话,那么它的点LA按道理就应该是32对吧?好,我们来试一下吧,我们还是打开这个号啊。我们定义一个function,比方说我们这叫test吧,简单一点啊,Public我们去,呃,我们现在是想要去找一个BEST32,对吧?好,我们去定义一个BA32。
23:02
这个returns一个好了,好,然后我们定义一个BEST32的数,呃,数据类型我们定义一个A好了。然后我们直接return a.Les大家看这个Les居然没有提示啊,这个感觉还是不是很合理的一个样子,大家看报了很多的这个呃,Warning大家可以看到,就是说。呃,像第一个这个warning的话,他说这个DEC declare declaration shadows啊一啊,这是我们已经定义过A了。上哪去了?好,呃,然后这里是我们没有去定义它的。Public这个是这里没有定义是吧,我们把下面删了吧。然后我们看这个网瘾报的是什么。
24:05
哦,就是它没有做任何的状态改改变,大家可以看到他说没有任何的状态改变,所以说你可以加一个指定,指定成纯函数,这个稍后我们再讲这个啊好,我们来让一下看看。好,我们看一下这个这个test,大家可以看到它的返回值就是一个32对吧,那如果说我们这里要是定义成一个,呃,我们奇怪一点啊,不要不要弄成这个这么常规的数,我们定义一个BY17。我们再来编编译部署一下。我们在这里看test一下,它就是17对吧,所以大家可以就是自己在这里随便找一个自己测试的一个一个合约,然后随便加各种各样的函数,这个就跟我们的car没有任何关系,也可以对吧,这就相当于是一个测试的纯函数,所以大家可以在这里自己去玩啊。
我来说两句