00:00
呃,有了这个表单之后,那么大家就会发现我们用户在网页上去点这个按钮的时候,Submit按钮的时候,他会带着这个product的ID,我们要做的处理是什么呢?是不是就就是直接调用这个合约里边最后结束的那个操作啊,那在这个合约里边我们就要改很多东西了,对不对,那我们要改什么东西呢?大家会想到我们在这个里边首先应该去。啊,我们首先就想到应该有一个新的一个方式,对吧,用户再去点击那一个finalize按钮的时候,就相当于调用的是我们这个合约里边的函数啊,我比方说我们这个合约里面的函数也叫做finalize option吧,叫一样的一个东西啊final option,然后这个里面是不是应该有一个product ID对吧?Product ID,那大家想到这个是一个public类型的一个函数。
01:02
是要终结我们当前的这个拍卖。呃,那大家会想到,首先你传进来product ID,我们还是这个老方法对吧?大家看到前面我们只要是传product id1上来,是不是就先把对应的这个product对象先拿到我们这里,就是还是做一个同样的操作啊,Product memory product等于stores,再再回顾一下,我们怎么样拿到这个product对象呢?我们把它是存在stores这个商,整个这个商店里边的,对吧?那这个商店里边它又是一个什么样的数据类型呢?它是一个map mapping的嵌套。首先它是一个商家到所有它上架商品的一个映射,对吧,前面我们给的是商家的地址,然后后边我们再根据product ID把对应的那个product具体的这个。呃,这个结构体把他的信息拿出来,那商家的ID怎么去寻找呢?我们又有一个单独的mapping去存了,这个map叫做product ID store,这是我们把product ID传进去就可以查出来它属于哪个商家,对吧?所以这里边我们就把商家的I地址传进去,然后拿到对应的product ID,诶,这里。
02:26
Product is。There啊,这是没有用是吧,这个没关系啊,对,没有用,所以接下来我们先拿到这一个product的对象,那然后我们要做什么事情呢?那大家就会想到我们finalize肯定是有一些条件的,对吧?那我们还是去require,首先我们require什么呢?那是不是这个当前时间我们首先。先不说是否要大于这个,就是我们定义的那个时间,对吧,首先我是不是至少它得大于那个antime呀,这个是肯定的对吧,Product点。
03:09
呃,我们当时叫什么来着,Option什么来着,看一下啊,Option对吧,我们把这个拿过来。product.option安排啊,这个是我们必须要有的一个,好,那么然后我们大家可以给一个,呃,这个说法对吧,就是比方说叫current time should be later。Than and time,大家随便写对吧?好,前面我们还是把这个表达式括起来。这里报了什么什么错啊,好,他是要求我们尽量避免用这个闹,对吧。
04:03
呃,这个应该没关系啊。Must be,哦,好吧,这个合约里边这要求比较严格,必须要用双引号,对吧。大家注意一下,如果在这个,呃,这个我们在JS里边单双引号,大家用习惯了之后,可能在合约里面就容易出问题,对吧,这里用双引号啊啊,这个now,当然它现在是不推荐用,我们暂时就还用它吧,之后大家知道就是这个now应该要换成什么,它这里有提示的,对吧,Block time STEM对吧,我们现在先不管啊好,那么接下来我们可能就会想到,我们如果要想关闭一个。这个product的它的这个拍卖的话,那首先我们product本身是有状态去记录它当前拍卖状态的,对吧?那是不是一开始我们就定义了这一个枚举类型,它是open sold on sold,这个这个其实就就在这里了,对吧?所以我们如果要结束一个状态的时候,是不是应该把它的这个这个状态要改变,对吧?那我们是不是首先应该要求他必须是一个open的状态啊?
05:14
所以我们product.status要求它必须等于我们的枚举类型product status。点open对吧,啊,这是我们要求的这样的一个状态的这样的一个要求啊,后面跟一个要求。Product status should be open,好,那我们在想,现在还要什么样的要求呢?结束,结束这样一个option。好,那我们前面说了,你要结束的话,结束的这个人调用的这个人就是我们的仲裁人对吧,阿比特,那这个@不能是塞塞,也不能是buy,对不对,不能是买家,也不能是卖家对吧?啊,这个我们首先是要明确的,所以我们首先不能是卖家对吧?Require message点三。
06:23
不等于,呃,大家想一下卖家怎么找这个卖家怎么怎么说呢。我们现在有了product的ID对不对?想一想一开始我们查他的时候详细信息的时候,这个是不是就是卖家信息啊,卖卖家的地址啊,对吧?所以我们是在product ID in store里边去存了这个卖家的地址的product ID in store,然后我们传入ID,这就是我们的卖家地址对不对?好,所以这里我们还是给一个。
07:03
呃,这个要求吧,我们说这个po should not be,这个是卖家对吧?C,好,然后我们require,还得要求不能是买家对吧?S不等于买家是谁。买家怎么拿?买家的信息是不是就是我们现在对竞拍结束的时候,他的那个highest bit啊,对,这就是买家对吧?所以我们这里边应该要求就不能等于product.high high highest b就不能等于这个值对吧?所以后边我们给一个要求说coll should not be fire,所以大家看这就是我们在去结束这样一个拍卖的时候,我们所需要的这些这些东西,那这些东西就是大家会发现我们梳理一下它的状态,首先应该是open的,然后它的时间我们有要求至少得大于这个option and time对吧,当然大家也可以定义一个我们必须是大于它加多少。
08:18
呃,就是我们必须在option and time之后,然后又过了一段时间之后,大家知道这个end time之后是需要去揭示报价的,对吧?那我们可以要求他还得在揭示报价之后,再过多长时间之后才能够去做这个最后的终结finalize,这个就大家可以去自由定义啊,我们这里就我们这里就不去写了,好,那么我们接下来,呃,大家会看到我们要求了这些,而且要求这个me th不能等于买家,也不能等于卖家,那么接下来我们就要去终结这个拍卖了,对吧?那大家会想到终结拍卖的时候,我们其实是要做什么事情呢?是不是就要创建那个托管合约啊。
09:07
啊,那首先这里边就又还区分两种情况。那大家可能会想到,有可能我们这个拍卖是不是就没没成功啊,就相当于没有买家,呃,没没有买家去竞拍对不对啊,这也是有可能的,所以这个时候。我们首先还得去应付一下,判断一下对不对啊,那大家会想到怎么判断当前有没有这个卖家呢?有没有买家呢?可以用he be是不是的,这个地址是不是等于零,还有另外一种方法,之前我们也说过可以叫什么product,有一个参数叫total bes对不对?对,偷偷币子,如果要是说它等于零的话,那么我们这个就简单了,这个就不用去创建托管合约对不对,直接把它关了就完了嘛,所以那这个时候我们也得去更改一些状态,更改什么呢?就是product。
10:06
Product status应该要等于product,大家还记得吧?Product status里边有一个枚举类型叫什么?它是不是open完了之后是sold on sold卖掉没有对不对,我们现在是不是应该就是on sold呀,啊,所以这里是枚举类型的ONSSO好。好,那接下来就是L对吧,L的话那就是已经卖出去了。至少是有人去竞拍,那我们就至少是可以卖出去了,对吧?那注意这里如果我们要已经卖出去的话,是不是就可以创建我们的合约了,那要创建我们的托管合约,是不是上边应该先把我们的托管合约先先引入进来啊,就比如说我们这里创建一个托管合约,怎么样创建,是不是就就这样去创建as pro对吧,As pro,然后我们等于new一个ice对不对,那如果我们想这么写的话。
11:13
现在我们这里是不是没有pro这样一个一个对一个变量对吧,一个类型,所以大家看一下,我们之前还没有专门这么写过,对不对,我们这里就要import。然后对,大家会想到contract。下边的就叫。点对吧,我们把这样的一个文件引入进来。那如果我们把这样的一个文件直接引入进来,Iport进来之后,我们就可以用as pro这个对象了,所以这其实这就是大家很习惯的这种从另外一个文件去引入对象,对吧?引入变量这些其实就是这么简单,调用另外一个合约就就这么简单,好那么大家可以知道就是我们把写了这个inport之后,相当于就是把as as pro solidity这个文件里边的那个整个contract都copy过来了,对吧?所以如果copy过来,我们是不是大家写过简单的那个合约调用是在同一个文件里边写不同的contract,然后下面就可以调了,对吧?那我们这里边就相当于import就把它copy过来了。好,那么接下来我们要做的事情就是要去真正的。
12:36
在这里去处理了对吧,好,那么我们直接new一个I。嗯,哪个photo子是吗?为什么不能用,因为人家进价了,但是人家没有去去。就例子去哦,就是有可能会出现没有去做review的这种情况,对吧?对,大家记得当时我们在已经竞价之后,如果要是没有review的时候,会发现它的total be子是有的,但是highest beer没有,对吧?对,所以这个有道理啊,我们把这个改一下,所以这个我们可以改成product.highest bid,如果这个地址等于零的话,那就没办法了,对吧,那就肯定他是没有没有竞拍成功的,好我们用这个来判断。
13:34
非常好啊,这个非常有道理,我们是不是课件上用的是total壁子是吧?对,所以大家可以把这个改过来啊,就是我们把这个改成high be来来做判断,呃,因为这个total be子的话,这个很容易,就是如果没有做最后的这个review的话,那其实大家会想到我们在这个处理的过程当中,只有在我们这个review BI的过程当中,才会把对应的这个highest BI啊,这些这个我们的second highest BI啊才会写进去,对吧,然后才会把对应的这个refund会会去退回给那个对应的那个人,如果说啊,他就当时发出来的那个以态就不要了,对吧,我就没有做这个review,那这个就还真是没办法,就就这个他真的是数据都没有写进去,然后这个以太也没有退回去,那这种状态下,我们确实是就不应该认为这个是拍卖成功的状态,对吧。
14:34
好呃,所以这个产品设计上大家会发现可能还是有点问题的,就是说别人真的如果要是说这个已经。已经竞拍了,把以太打过去了,然后没有review,那相当于在我们这个逻辑里边,就把这个金额就直接锁死在里面了,对吧,就真的就拿不出来了,所以这个看起来我们其实大家可以再去改进啊,再去想我们怎么样把这个逻辑处理好,你不能说我这个一旦我错过review的那个时间,最后我就真的这个钱就怎么都拿不出来了,这个看起来还是不应该的,所以大家可以再去多加一个额外的一个函数,比方说就是说去拿这种对吧,无效的,或者说已经承诺的这个以态,呃,特殊的一个transfer,这可能就得超级权限对吧,可能需要是我们真正和约创建者啊,或者是谁才能把这个提出来,好,那么我们现在不说这种就是比较,呃,比较这种这种就是边缘的这种更多的这种考量,我们现在主要是考虑去创建这样一个我们的as as astro合约,那这里边大家要注意一下。
15:44
我们创建as合约的时候,肯定就是new as,然后加上这些参数对吧。啊,这里大家要稍微注意一下我们这里的pro,大家可以看一下我们这里课件里面的实现啊,大家可以看它的实现是什么呢?它是把前面的new X给括起来了。
16:03
然后后边用了什么呢?点value修饰器对吧?大家还记得吗?这个点value是什么?我们调用一个合约函数的时候,是不是可以点value.guess给它做修饰,就相当于是我们调用合约的时候也要带着一个以态,带着一个guess对吧?限定的那个guess数量可以用这个来修饰,因为大家可以想到这是合约,调用合约,这是发发送一个消息,但这个消息其实也可以带着T,对吧。那所以这个方式跟我们的那个发送交易的时候带以他带GA其实是类似的,所以它都是用这样的方式去去发送的,那这里大家就注意我们这里的调用的这个函数是什么呢?其实是new as pro,这个其实就是调用了它的constructor对不对,就大家可以认为前面的new pro就是as pro.constructor。
17:02
可以这么认为啊,但是不能这么写,对吧,我们都要写U。所以点value,这里是要带着的以态的数量,然后后边又跟了一个括号,这个是不是才是我们constructor的参数啊,所以大家把这个要搞清楚啊,所以这个参数,这是我们当时指定好的这些参数。好,呃,那么接下来我们就去把这个去实现一下,这个时候大家其实就会发现一个问题,发现什么问题呢?我们回过头来看一下我们当时的这个as pro,这个它的constructor。我们这里的constructor给定的是就是这个product product ID,然后三个参与人对吧?啊,这些都没问题,然后我们把他的这个value就给到这个amount里边,对吧。这个也没什么问题,但是大家要注意,在他这样创建之后,我们如果要是想要调用这个release amount to sell的时候,那就必须我们创建之后就一定要是真正那个人,他得去调用我们这个方法对不对?
18:18
那它调用的时候,大家会想到我们是不是在,就是如果调用这个方法的时候。在JS里面怎么样去调用,是不是得先拿到它的合约实力啊,但是在这个过程当中,我们不是直接就像就像trouble一样,我们直接把这个合约我们手动去给他部署上去的,对不对?它部署的过程是什么呢?是我们在这里边有一个人去调用这个final final的时候是不是就部署一遍啊,相当于new一个合约出来,所以这个过程。是不是大家会发现我们似乎就没有办法直接拿到它的地址是什么,它的地址是不是应该在我们扭出来之后,存在这个就是imss里面去啊。
19:09
啊,所以是这样的一个过程,对吧,所以大家会发现,如果我们这个合约就是在e com store里面去创建的话,那么它的所有的调用信息是不是都应该存在这个里面。啊,所以这个时候大家就会发现了,我们的调用方法其实就会不一样,我们正常来讲就应该全部从我们这个e com store里边去调用as pro这个合约,对吧?所以后面的实现也会有所不同,好,那现在我们先不说那么多,我们先把眼前这个创建合约先弄出来,然后我们这里就可以点Y6对不对,把我们对应的这一个金额传递进去,对应的这个金额应该是什么呢?这里要传的金额是什么呢?我们这里没有value啊。
20:03
我们这里是value吗?不是,这这个mes center,这是们的调用结束拍卖的这个人对吧,这是我们的仲裁人对吧,他肯定不会发以太过来,而以太现在是不是已经在我们这个合约里面有了,所以我们是直接点value要传的那个值是我们当前product。他的竞拍成功的那个价格对不对?最后要支付的价格,最后要支付的价格是什么呢?Product点还记得吗?对,Second highest speed啊,就是第二高价就是要支付的对不对,所以大家就把这个逻辑串起来啊,到这个时候我们就是把之前的所有的逻辑都得串起来了,好那么接下来这是后面跟一个括号,这是我们要给的这个参数对不对?所以这个参数里面有什么呢?首先product ID,这个product ID。
21:08
这里的product ID是什么?是传进来的这个product ID对吧?所以我们下划线product ID,然后第二个参数我们看一眼是cellar,好,后面就是cellar buyer和这个abi对吧?那ser应该是谁呢?应该是我们这里边是不是还是前面我们这里定义的这个东西啊,啊,当然当然,如果要是觉得比较麻烦的话,可以直接把它拿出来当一个sell变量存起来,对吧?啊,我们这里就还是用这个方式把它拿出来就好了。Product product应该是从这个product ID install这个mapping里边,按照product ID把它存取出来,对不对,后面是product ID,好,这是我们的,然后接下来是buy。
22:04
Buyer是什么呢?啊,那前面其实我们这两个都用过了,对不对,一个是buyer,一个是seller,对吧,这里我们就再写一遍product.highest BI就是我们的buyer对吧?然后最后一个是message.sender。是不是我们的mes sender是不是就应该是我们当前的这个仲裁人啊,啊,就是我们这么定义的,对吧?所以我们把仲裁人写成message.send好。那这个合约调用,我们看一下他哪里有错。Is declared but not used对吧?这个错我们不用管啊,好,那接下来大家注意,我们已经定义了这一个。就是这个合约对象之后,那么我们是不是刚才已经想到了,我们之后要调用的时候,是不是得先拿到这个它的合约地址啊。
23:03
所以说我们现在调用之后,这个s pro,它直接它转成这个,我们知道每一个合约其实都是一个以太坊里面的账户,对不对,我们直接dress做一个强制类型转换,诶这个S拼错了是吧?S pro我们做一个强制类型转换,是不是就能拿到它的这个对应的地址。但是我们现在只有在它创建的时候能这么用一下,以后我们想调用的时候。想要用的话,是不是我们得把它存起来啊,所以这个地方大家就会注意,我们前面是不是还得再定义一个数据结构啊,好,那我们前面继续多定义一个数据结构啊,数据结构定义在最前面,好,那这个数据结构大家想象一下我们应该是跟谁相关呢?诶,我们这个。哦,我还以为少了大括号啊,不是,大家想想,我们这个数结构应该是放在product里边,还是放在B的里边,还是放在别的地方呢?
24:10
就是要存我们对应的这个。要存对应的地址对吧,我们这个应该放在哪里。呃,大家觉得应该是放在product里边对吧?啊,我们如果要去方便查询的话,当然大家可以放在product里边。如果我们要去筛选的时候,那大家还是就应该是传进来一个product ID对吧?然后我们拿到product,从这个ID拿到他的这个商家的信息,然后根据他的商家信息和product ID拿到在stores里边拿到对应的这个product ID,然后product ID点它的那个对应的合约的那个地址,对不对,拿出来可以这么去做,但是我们还有更简单的一个方法,就是我们直接放在外面对吧?对,我们这这里不是定义了这么多mapping嘛,Mapping其实就是方便检检索对不对,这个你既然我们是单独的用途,那其实可以单独把它拿出来的,单独拿出来是什么呢?因为我们不需要知道。
25:17
就是我们最后在想要拿到他的合约地址的时候,其实我们不需要知道product所有的这些信息对不对,我们只要知道一个ID就可以了,所以我们不需要再通过product这么一串一大堆东西再去做检索,那我们是不是可以直接用product ID就是一个U对不对,直接对应一个dress。这样是不是就可以直接查出来了,一个麦屏搞定对吧,这样会简单一点,所以这个我们定一个叫叫什么。呃,叫product astro,那这个还是很明确的一个一个明命名,对吧?Product astro也就是代表了我们当前这个,呃对应的product ID,它对应的那个托管合约的地址在哪里?好我们那接下来我们是不是就应该已经拿到这个合约对象之后,是不是先把它给存进去了,好那么接下来这个应该是我们这个负值的一个右值对吧?我们的左值应该是什么呢?那就应该是product刚定义的对吧。
26:22
Product叫什么?Product pro是吧?Pro,然后里边对应的就是product ID对不对?呃,Product ID它就应该等于address做一个强制类型转换,然后as我们刚刚创建出来的这一个合约对象对吧?创建出来出来之后把它存进去好,那么接下来我们已经把它存进去了,接下来我们就要把这个合约完结的这个状态还是做一个处理了,对吧?那首先这个status之前是on so的,那我们现在是不是同样应该是的呀,这个是正常的一个梳理,对吧,Product status点。
27:13
好。呃,这里已经把它sold完成之后,那么我们这里还应该做一个什么事情呢?状态也改变了,这个地址也已经存起来了啊,大家觉得是不是我们该做的事情都已经做完了?还有什么事情没有做?那大家要注意,我们之前在这个review BI的过程当中,大家还记得我们这个退款的过程,对吧,我们是先判断你是不是进价是最高的high bier,呃,然后呢,我们会去要求,呃,就是然后大家会发现如果你不是highest BI的话,相当于就把这个所有的款项我们就直接都退回去了,对不对,对吧,就是你当前的这一个发过来的这个款项就全部都退回去了,但是如果你是最高竞价人的话,你是high逼的话。
28:12
这里当时退的款是什么呢?退的是你给的那个押金,对吧?当时你给过来的以太坊数量,然后对应的那个amount要减掉对不对,相当于现在我们在合约里边已经扣着的他的押金,还留着的这个high BI,别人的都已经退回去了,对不对?Highest biter它是扣了一部分以态的,那这会儿扣着他的以太数量是。是多少?是它的哪个哪个数量。我们现在对应的就剩两个数量对吧,他一开始给的那个数量,我们多的都已经返返回去了,那现在它里边存着的就是扣着的,它的以态数量是它的竞拍价格。也就是说是highest b的呢。
29:00
还是second?应该是highest be对不对?因为当时我们是这个value比amount多出来的部分退回去了,而且我们当时还不知道他最后假如说他能竞价成功的话。他要给的钱是多少,因为你还不知道第二高竞价,还有可能有人竞争过来之后,把第二高竞价顶掉对不对,所以还不知道他最后要付多少,所以我们是按照他的竞拍价格把他的以太全扣在这里的。那现在我们要结束这个拍卖了,结束拍卖的时候,我们这里发的是第二高价,也就是他最后真正要付的那个钱给到了托管账户,那这个是不是他有可能他本身的竞拍价格比这个第二高竞价要高啊。那是不是多余出来的部分,我们应该还记得给他退回去,所以这个时候我们应该给他退回一部分金额,那这个金额是什么呢?我们定义一下,还是叫做refund吧,之前我们的回款退款都叫refund,对吧?这个应该是什么?就是它的highest b对吧?这是它的出价product.highest。
30:16
B减掉是不是second b呀。对,所以我们这里把这个减掉,这就是我们应该给他回款,现在退回去的东西,那之后给到合约托管合约那里的,就是他最后真正应该支付的第二高进价,对吧?然后所有的款都给他退,退回去了,都干净了,都清理干净了,所以这个就没有别的问题了,对吧?那当然这个已经定义了refund之后,我们是不是要给他退款了,退款怎么退呢?地址点transfer,对不对,Transfer refund,我们先把这个写出来,那前面的地址应该是谁呢?这是我们的。
31:01
这是我们的buyer对不对对,所以又是前面那一串对不对?product.highest bit啊,当然大家如果觉得我们后面用到了太多次的话,想在前面把ser定义出来也是可以的,对吧?好,product.highest。点transfer就搞定这件事情了,好,那么大家可以看到我们这就处理了这个high BI到底有没有的这样的一个两种情况啊,那大家看我们现在是不是已经把这个事情做完了呢。啊,这里要跟大家说一句,大家回看一下我们的这一个课件啊,大家会发现我们好像还少一句,对不对,这一句是什么呢?这一句是因为大家看一下我们这里前面给到的这个变量类型是什么memory类型。Memory类型,那我们变了这么多,这么一大坨这个memory,我们让它等于stores里边,这是我们的这个状态变量里面的东西,对不对?我们把状态变量里面这个存在storage里边,我们把它付给memory类型的时候,是不是这是完全拷贝了一份,拷贝在我们内存里边了,那我们这里再去更改它的时候,是不是你这只更改了内存里面的这个product呀,那我们状态变量是不是没改啊?
32:23
所以说我们这里是不是最后结束的时候还得把状态变量再刷回去,对,所以大家会看到我们的这个story stores里边对应的我们这个product,那是product ID in store,对吧,这是卖家的商家的这个地址。然后那大家会看到后边我们还要把这个product ID拿出来,对吧,Product ID,这就是整个的这一串,这是我们在。
33:05
我们的状态变量里边storage里边存着的这个product数据,对吧?我们得把这个product是不是在用我们这个memory里边的这一个再给它刷回去啊,再赋值一下memory到storage的赋值,这又是整个全copy进去,对不对,这就更改了我们的状态变量对吧?所以大家不要忘记这样的一句啊,就是最后再把我们这个刷回去,当然大家可以想到我们是不是可以不这么笨,不这么做啊,对,那大家想到我们前面这个是不是直接定义一个storage类型就不会有这样的事啊,定义storage类型之后,是不是这个我们的product就变成了它的一个。引用对不对?所以我们变product,这里我们都在改product,是不是就相当于变了我们的状态变量对吧?所以这是两种写法啊,这里我们就按照这个课件的写法给大家说,大家如果实现的时候可以把这里直接用story写,对吧?大家其实看到我们前边应该也用到了这种写法,对不对?
34:09
我们在review be的时候,是不是就直接product storage把它定义出来,后边我们就没有再把product刷回去,对不对,对吧,就直接product的所有操作完了就完了啊,所以大家其实也是知道我们是有这样的操作的啊,我们用两种方式,你看BI的这个过程也是这样,用storage把它更改了就完了,对吧,这里就给它大家多一种操作方式,如果大家这里用了memory的话,一定记得最后再把它刷回去。啊,当然这个也有好处,就是什么呢?我们相当于是一次性改变这个状态变量对不对,有可能,当然这个没有具体测试过啊,大家可以去试一试,可能这个盖会少耗一点,大家可以试一下。
我来说两句