00:00 |
We started working on the function mint.
我们开始着手实现mint函数。 |
00:02 |
This function calls an internal function called
这个函数调用了一个内部函数,名为 |
00:04 |
modifyPosition. The function modifyPosition calls another internal function called updatePosition.
modifyPosition。函数modifyPosition又调用了另一个内部函数,名为updatePosition。 |
00:10 |
Inside the function updatePosition, there are some code that updates the ticks.
在updatePosition函数内部,有一些代码用于更新ticks。 |
00:14 |
So today we'll be working on ticks.update and ticks.clear. Inside our code,
所以今天我们将处理ticks.update和ticks.clear。在我们的代码中, |
00:19 |
I'll declare a state
我将声明一个状态 |
00:21 |
variable called ticks, and this will be a mapping from int to for to a struct
名为ticks的变量,这将是一个从int到for的映射,映射到一个结构体 |
00:27 |
called tick.info.
名为tick.info。 |
00:30 |
We have not defined the struct yet, so we'll do that later. This will be public,
我们还没有定义这个结构体,所以稍后会定义。这个将是public, |
00:34 |
and then I'll name
然后我将命名为 |
00:35 |
it ticks. Int to for will be a tick, and then from here it maps to
它为ticks。Int到for将是一个tick,然后从这里映射到 |
00:39 |
some kind of data that stores the
某种存储信息的数据 |
00:41 |
information at this tick. Okay, let's go define a struct called tick.info. Inside my vid,
在这个tick上的信息。好的,让我们定义一个名为tick.info的结构体。在我的vid中, |
00:47 |
click on tick, and inside here we'll create a struct,
点击tick,在这里我们将创建一个结构体, |
00:51 |
struct info. And what information do we need to store
结构体info。我们需要存储什么信息 |
00:55 |
here? Let's go to the Uniswap V3 code to find out what data we need to store inside here.
在这里?让我们去Uniswap V3代码中找出我们需要存储的数据。 |
01:01 |
Here's the code inside Uniswap V3. I'll copy all this code and then paste it over to our code.
这是Uniswap V3中的代码。我将复制所有这些代码,然后粘贴到我们的代码中。 |
01:07 |
Here's the code that's copied over from Uniswap V3. Okay,
这是从Uniswap V3复制过来的代码。好的, |
01:10 |
let's go one by one. Liquidity growth. This
让我们逐个来看。流动性增长。这 |
01:13 |
will be the total liquidity inside this tick.
将是这个tick内的总流动性。 |
01:16 |
Liquidity net is the amount of liquidity that needs
流动性净值是需要 |
01:19 |
to be added or removed when this tick becomes active.
在这个tick变为活跃时需要添加或移除的流动性。 |
01:23 |
Fee growth outside 0x128 and fee growth
0x128外的费用增长和 |
01:26 |
outside 1x128. These are data that is needed to calculate the fees. Tick cumulative outside,
1x128外的费用增长。这些是计算费用所需的数据。tick的累积外部, |
01:32 |
and the next two data are data related to the price oracle,
接下来的两个数据与价格预言机相关, |
01:35 |
so we won't need these.
所以我们不需要这些。 |
01:37 |
And boolean initialized, whether this tick is initialized or not. Okay,
还有一个布尔值initialized,表示这个tick是否已初始化。好的, |
01:40 |
so this is the struct that
所以这是我们需要的结构体。 |
01:42 |
we're going to need. Let's go back to our clam contract. Make sure that we have tick imported.
我们将需要的。让我们回到我们的clam合约。确保我们已经导入了tick。 |
01:47 |
Scroll up, and we have tick imported. Okay,
向上滚动,我们已经导入了tick。好的, |
01:50 |
next let's add this library to our clam contract.
接下来让我们将这个库添加到我们的clam合约中。 |
01:54 |
So here I'll say using tick for the mapping, which we've declared over here. So I'll just copy this,
所以在这里我将说使用tick进行映射,我们在这里声明过。所以我将复制这个, |
02:02 |
then paste it here. For the mapping from int24 to tick.info. Next,
然后粘贴到这里。从int24到tick.info的映射。接下来, |
02:08 |
let's actually implement the functions that we need inside the tick contract.
让我们实际实现我们在tick合约中需要的函数。 |
02:12 |
So first I'm going to go back to the Uniswap V3 pool
所以首先我将回到Uniswap V3池 |
02:15 |
contract. And what are the functions that we're going to be calling? The first function that we're
合约。我们将调用哪些函数?我们将调用的第一个函数是 |
02:20 |
going to be calling is called ticks update.
将要调用的函数称为ticks update。 |
02:23 |
And the other function that we're going to be calling
我们将要调用的另一个函数是 |
02:25 |
is called ticks clear. Let's take a look at what these functions do. So I'm going to open tick.sol
称为ticks clear。让我们看看这些函数的作用。所以我将打开tick.sol |
02:31 |
inside Uniswap V3 code and look for a function called update.
在Uniswap V3代码中,寻找一个名为update的函数。 |
02:35 |
And then I'll copy this function signature over to our code. Okay,
然后我将把这个函数签名复制到我们的代码中。好的, |
02:40 |
here's the function update. The first input is going to
这是函数update。第一个输入将是 |
02:44 |
take in the state variable from int24 to tick.info. Inside our clam contract, we declare this,
接收从int24到tick.info的状态变量。在我们的clam合约中,我们声明这个, |
02:50 |
we name this state variable as ticks. So here we're going to pass in the state variable ticks.
我们将这个状态变量命名为ticks。所以在这里我们将传入状态变量ticks。 |
02:57 |
Okay, next parameter is a tick,
好的,下一个参数是一个tick, |
02:59 |
the tick that we're going to be updating. Next one is the current tick.
我们将要更新的tick。下一个是当前tick。 |
03:03 |
This will be stored in slot0, liquidity delta, some variables that are related to the fees,
这将存储在slot0中,流动性增量,一些与费用相关的变量, |
03:09 |
and the next three parameters. We're not going to need it.
以及接下来的三个参数。我们不需要它们。 |
03:12 |
These are parameters that's related to the
这些是与 |
03:14 |
price oracle. The next variable, upper, means whether the tick is a upper tick or a lower tick,
价格预言机相关的参数。下一个变量upper,表示这个tick是上tick还是下tick, |
03:20 |
and max liquidity. And what does it return? It returns a boolean called flipped.
以及最大流动性。它返回什么?它返回一个名为flipped的布尔值。 |
03:25 |
Flip means that this will be true when the liquidity gets activated or deactivated. Otherwise,
Flip表示当流动性被激活或停用时,这将为true。否则, |
03:30 |
it will return false.
它将返回false。 |
03:32 |
If liquidity is equal to zero, and after we call the function update,
如果流动性等于零,并且在我们调用函数update后, |
03:36 |
liquidity becomes greater than
流动性变为大于 |
03:37 |
zero, then flipped will be equal to true. Another case where the flipped will be true is if liquidity
零,那么flipped将等于true。另一个flipped为true的情况是如果流动性 |
03:43 |
is greater than zero, and after calling the function update,
大于零,并且在调用函数update后, |
03:46 |
liquidity is equal to zero. So these are the
流动性等于零。所以这些是 |
03:49 |
two cases when this boolean flipped will return true. Okay,
这个布尔值flipped将返回true的两种情况。好的, |
03:51 |
the first thing that we'll do is load the
我们要做的第一件事是加载 |
03:54 |
tick into memory. So say info memory, I'll name it info,
tick到内存中。所以说info memory,我将命名为info, |
03:58 |
is equal to self. This will be a state variable at the tick. Next,
等于 self。这将是 tick 的一个状态变量。接下来, |
04:02 |
we'll store the liquidity goes before and after into a local variable. Say
我们将把流动性在之前和之后的值存储到一个局部变量中。比如说 |
04:07 |
uint128 liquidity growth before. This will be stored in info.liquidity growth.
uint128 流动性增长之前。这将存储在 info.liquidity growth 中。 |
04:15 |
And then also liquidity growth after. This will be the previous liquidity.
然后还有流动性增长之后。这将是之前的流动性。 |
04:21 |
So this will be stored in liquidity growth before
所以这将存储在流动性增长之前 |
04:24 |
plus liquidity delta. Now liquidity delta is int128. However,
加上流动性增量。现在流动性增量是 int128。然而, |
04:29 |
liquidity growth before is uint128.
流动性增长之前是 uint128。 |
04:31 |
So we'll have to either add or subtract depending on whether liquidity delta is positive or negative.
所以我们必须根据流动性增量是正还是负来加或减。 |
04:38 |
So I'll say liquidity delta is less than zero. If liquidity delta is less than zero,
所以我会说流动性增量小于零。如果流动性增量小于零, |
04:44 |
then liquidity growth after will be liquidity growth before minus cast liquidity delta into uint128.
那么流动性增长之后将是流动性增长之前减去将流动性增量转换为 uint128。 |
04:52 |
Since this is negative,
因为这是负数, |
04:53 |
we'll need to bring it to positive first. So say minus liquidity delta.
我们需要先将其变为正数。所以说减去流动性增量。 |
04:58 |
Otherwise, liquidity growth before plus cast liquidity delta, which is not negative,
否则,流动性增长之前加上将流动性增量转换为 uint128,这不是负数, |
05:04 |
cast it into uint128.
将其转换为 uint128。 |
05:06 |
Okay, next we'll check that liquidity growth after is less than or equal to max liquidity.
好的,接下来我们将检查流动性增长之后是否小于或等于最大流动性。 |
05:12 |
So here I'll say require liquidity growth after should be less than or equal to max liquidity. Error message,
所以在这里我会说要求流动性增长之后应该小于或等于最大流动性。错误信息, |
05:20 |
liquidity greater than max.
流动性大于最大值。 |
05:21 |
Okay, the next thing that we'll do is compute whether this liquidity has been flipped.
好的,接下来我们要做的是计算这项流动性是否已经翻转。 |
05:26 |
Again, we return true for flipped if liquidity has been activated or it has been deactivated.
如果流动性已被激活或已被停用,我们将返回 true 表示翻转。 |
05:32 |
For liquidity to be activated,
流动性被激活的条件是, |
05:33 |
it means that liquidity growth before was equal to zero and
这意味着流动性增长之前等于零,并且 |
05:37 |
liquidity growth after is greater than zero.
流动性增长之后大于零。 |
05:39 |
For liquidity to become deactivated, it's the opposite.
流动性变为停用的条件正好相反。 |
05:43 |
Liquidity growth before was greater than zero and liquidity growth after is equal to zero.
流动性增长之前大于零,而流动性增长之后等于零。 |
05:48 |
Now, if you take a look at the tick sole inside Uniswap V3 code, it does
现在,如果你查看 Uniswap V3 代码中的 tick.sol,它执行了 |
05:53 |
this confusing check to calculate flipped.
这个令人困惑的检查来计算翻转。 |
05:56 |
So what I'm going to do is copy this and then I'm going to explain how
所以我将复制这个,然后解释一下 |
06:00 |
this code is exactly the same as this situation.
这段代码与这种情况是完全相同的。 |
06:04 |
So here's the code from Uniswap V3 and here is the condition for being flipped.
这是来自 Uniswap V3 的代码,这里是翻转的条件。 |
06:09 |
Let's see how these two code does exactly the same thing.
让我们看看这两段代码是如何完全相同的。 |
06:12 |
If this part is true, then we are looking at this case,
如果这一部分为真,那么我们正在查看这个情况, |
06:17 |
liquidity growth after is equal to true.
流动性增长之后等于真。 |
06:20 |
And in that case, liquidity growth before must be greater than zero,
在这种情况下,流动性增长之前必须大于零, |
06:24 |
which is exactly the same as saying liquidity growth before equal to zero.
这正好等于说流动性增长之前等于零。 |
06:29 |
This part should evaluate to false.
这一部分应该评估为假。 |
06:31 |
We have this part evaluating true and this part evaluating to false.
我们有这一部分评估为真,而这一部分评估为假。 |
06:36 |
So in this case, flipped will be equal to true.
所以在这种情况下,翻转将等于真。 |
06:38 |
Likewise, if liquidity growth after is equal to true returns false,
同样,如果流动性增长之后等于真返回假, |
06:42 |
then we are looking at this case.
那么我们正在查看这个情况。 |
06:45 |
In that case, liquidity growth before must be equal to true, which is this case.
在这种情况下,流动性增长之前必须等于真,这就是这个情况。 |
06:52 |
This part will be equal to true and this part will be equal to false.
这一部分将等于真,而这一部分将等于假。 |
06:56 |
And again, flipped will evaluate to true.
而且再次,翻转将评估为真。 |
06:58 |
So this code over here is a concise way to express this condition.
所以这段代码是表达这个条件的简洁方式。 |
07:03 |
Okay, let's move on.
好的,我们继续。 |
07:04 |
What do we have to do next?
接下来我们要做什么? |
07:05 |
So going back to tick.sol inside Uniswap V3 code, the next part of the code
所以回到 Uniswap V3 代码中的 tick.sol,接下来的代码部分 |
07:10 |
that I'll explain is this part.
我将解释的是这一部分。 |
07:12 |
If liquidity growth is equal to zero, for now we will ignore this part.
如果流动性增长等于零,目前我们将忽略这一部分。 |
07:16 |
This part of the code relates to calculating the fees.
这部分代码与计算费用有关。 |
07:20 |
Then set info.initialize equal to true.
然后将 info.initialize 设置为 true。 |
07:23 |
Okay, let's write this part of the code into our contract.
好的,让我们把这部分代码写入我们的合约。 |
07:26 |
If liquidity growth before is equal to zero,
如果流动性增长之前等于零, |
07:31 |
then set info.initialize equal to true.
那么将 info.initialize 设置为 true。 |
07:35 |
Okay, what's the next part?
好的,下一部分是什么? |
07:37 |
Going back to Uniswap V3 code.
回到 Uniswap V3 代码。 |
07:39 |
So it looks like we update liquidity growth to liquidity growth after.
所以看起来我们将流动性增长更新为流动性增长之后。 |
07:44 |
Okay, let's also do that inside our code.
好的,我们也在我们的代码中这样做。 |
07:46 |
Say info.liquidity growth is equal to liquidity growth after.
说 info.liquidity growth 等于流动性增长之后。 |
07:53 |
Okay, going back to Uniswap V3 code again.
好的,再次回到 Uniswap V3 代码。 |
07:55 |
The last part is setting liquidity net.
最后一部分是设置流动性净值。 |
07:59 |
If it is an upper tick, then we subtract liquidity delta from liquidity net.
如果这是一个上限 tick,那么我们从流动性净值中减去流动性增量。 |
08:04 |
Otherwise, then we add liquidity delta to liquidity net.
否则,我们将流动性增量加到流动性净值中。 |
08:08 |
Going back to our code.
回到我们的代码。 |
08:10 |
Here's a brief explanation of what the code does.
这是对代码功能的简要说明。 |
08:13 |
As the price moves from left to right to the current liquidity,
当价格从左到右移动到当前流动性时, |
08:16 |
we will add liquidity net.
我们将增加流动性净值。 |
08:17 |
So let's say that the current price is over here, below the lower tick.
假设当前价格在这里,低于下限刻度。 |
08:22 |
And then as the price moves from left to right, this tick will become active.
然后,当价格从左到右移动时,这个刻度将变为活跃。 |
08:26 |
So to the current liquidity, we add this positive number liquidity net.
因此,我们将这个正数流动性净值添加到当前流动性中。 |
08:31 |
And as the price further moves from left to right,
当价格进一步从左到右移动时, |
08:34 |
the upper tick will become deactivated.
上限刻度将被停用。 |
08:36 |
And at that point, we minus liquidity net from the current liquidity.
在那时,我们将流动性净值从当前流动性中减去。 |
08:41 |
A similar situation happens when the price moves from right to left.
当价格从右向左移动时,也会发生类似情况。 |
08:45 |
When the current tick crosses the upper tick, moving from right to left,
当当前刻度从右向左穿过上限刻度时, |
08:50 |
the liquidity net that is stored here is negative.
这里存储的流动性净值是负的。 |
08:53 |
So to this liquidity net, we minus.
因此,我们将这个流动性净值减去。 |
08:55 |
Minus minus becomes a positive.
减去负数变为正数。 |
08:57 |
So we're adding liquidity to the current liquidity.
因此,我们将流动性添加到当前流动性中。 |
09:00 |
And as the price moves further to the left,
当价格进一步向左移动时, |
09:02 |
the current tick will cross the lower tick.
当前刻度将穿过下限刻度。 |
09:05 |
Here, the liquidity net that is stored is positive.
这里存储的流动性净值是正的。 |
09:07 |
And we do a minus.
我们将其减去。 |
09:08 |
So this will decrease the current liquidity by whatever value that is stored inside liquidity net.
因此,这将减少当前流动性,减少的值为流动性净值中存储的值。 |
09:14 |
For the lower tick.
对于下限刻度。 |
09:15 |
I'll explain how all of this works in another video.
我将在另一个视频中解释这一切是如何工作的。 |
09:18 |
So moving on, let's write the code.
接下来,让我们编写代码。 |
09:20 |
So say info.liquidity net is equal to.
假设 info.liquidity net 等于。 |
09:25 |
If it is an upper tick, then we store the negative.
如果是上限刻度,则我们存储负值。 |
09:27 |
If it is a lower tick, we store the positive.
如果是下限刻度,则我们存储正值。 |
09:30 |
If it is an upper tick, then to info.liquidity net, we minus this.
如果是上限刻度,则我们从 info.liquidity net 中减去这个值。 |
09:36 |
So say minus liquidity delta.
假设减去流动性增量。 |
09:39 |
Otherwise, we say info.liquidity net plus liquidity delta.
否则,我们将 info.liquidity net 加上流动性增量。 |
09:46 |
Okay, and that completes the function update.
好的,这完成了更新函数。 |
09:49 |
Next, let's write the function clear.
接下来,让我们编写清除函数。 |
09:51 |
So I'm going to open the ticks library inside Uniswap v3.
我将打开 Uniswap v3 中的 ticks 库。 |
09:55 |
And all it does is it's going to take in a mapping from int 2.4 to tick.info.
它的作用是接受从 int 2.4 到 tick.info 的映射。 |
10:01 |
This will be our state variable ticks.
这将是我们的状态变量 ticks。 |
10:03 |
It's also going to take in the tick to clear.
它还将接受要清除的刻度。 |
10:05 |
And all it does is delete this state variable.
它的作用是删除这个状态变量。 |
10:08 |
So inside our code, I'll say function clear.
在我们的代码中,我将定义函数 clear。 |
10:13 |
We're taking a mapping from int 2.4 to info.
我们接受从 int 2.4 到 info 的映射。 |
10:17 |
This will be a storage.
这将是一个存储。 |
10:19 |
I'll name it self.
我将其命名为 self。 |
10:20 |
And it's also going to take the tick to delete.
它还将接受要删除的刻度。 |
10:23 |
Int 2.4 tick.
Int 2.4 tick。 |
10:25 |
This function will be internal.
这个函数将是内部的。 |
10:26 |
And what we do is delete self of tick info.
我们要做的是删除 self 中的刻度信息。 |
10:31 |
Okay, going back up.
好的,回到上面。 |
10:33 |
Okay, that completes the function clear and update inside the library tick.
好的,这完成了库 tick 中的清除和更新函数。 |
10:40 |
Let's go back to Uniswap v3 pull contract.
让我们回到 Uniswap v3 拉取合约。 |
10:43 |
And next thing that we'll need to do is call those functions update and clear.
接下来,我们需要调用这些函数更新和清除。 |
10:47 |
Okay, let's work on this part of the code first.
好的,让我们先处理代码的这一部分。 |
10:52 |
So first, we declare two boolean variables called flip lower and flip upper.
首先,我们声明两个布尔变量,分别称为 flip lower 和 flip upper。 |
10:58 |
Okay, I'll do that inside my code as well.
好的,我也将在我的代码中这样做。 |
11:00 |
So just copy this and then paste it here.
所以只需复制这个,然后粘贴到这里。 |
11:04 |
Next, we'll need to call ticks.update if liquidity delta is not equal to zero.
接下来,如果流动性增量不等于零,我们需要调用 ticks.update。 |
11:09 |
So if liquidity delta is not equal to zero, you'll need to call ticks.update.
因此,如果流动性增量不等于零,你需要调用 ticks.update。 |
11:16 |
And what are the parameters that we'll need to pass?
我们需要传递哪些参数? |
11:18 |
Ticks.update.
Ticks.update。 |
11:19 |
The parameters that we'll need to pass is tick lower, tick lower, current tick, liquidity delta,
我们需要传递的参数是 tick lower、tick lower、current tick、liquidity delta, |
11:26 |
fee growth global 0x128, and fee growth global 1x128.
fee growth global 0x128 和 fee growth global 1x128。 |
11:32 |
The next three parameters are parameters for the price oracle,
接下来的三个参数是价格预言机的参数, |
11:34 |
so we'll ignore them.
所以我们将忽略它们。 |
11:36 |
And this is a lower tick, so we'll pass in false.
这是一个下限刻度,因此我们将传递 false。 |
11:39 |
And the max liquidity per tick.
以及每个刻度的最大流动性。 |
11:41 |
Calling the function ticks update will return a boolean whether this tick,
调用函数 ticks update 将返回一个布尔值,指示此刻度是否, |
11:44 |
this lower tick was flipped or not.
这个下限刻度是否被翻转。 |
11:47 |
So say flipped lower is equal to.
假设 flipped lower 等于。 |
11:51 |
We'll do the same for the upper tick.
我们对上限刻度做同样的操作。 |
11:54 |
So copy this, paste it here.
所以复制这个,粘贴到这里。 |
11:57 |
Rename this variable to flipped upper.
将这个变量重命名为flipped upper。 |
11:59 |
The tick that we're updating is tick upper.
我们正在更新的刻度是tick upper。 |
12:02 |
And then the other parameter that I'll change is this is a upper tick.
然后我将更改的另一个参数是这是一个上限刻度。 |
12:06 |
So I'll change this to true.
所以我将把这个改为true。 |
12:08 |
Okay, what's next?
好的,接下来是什么? |
12:09 |
Next, if tick is flipped, then it calls tick bitmap.
接下来,如果刻度被翻转,那么它会调用tick bitmap。 |
12:12 |
We'll skip this for now.
我们暂时跳过这个。 |
12:14 |
And what's next?
接下来是什么? |
12:15 |
The next part is calculates the fee and then updates position.
下一部分是计算费用,然后更新位置。 |
12:20 |
Update position.
更新位置。 |
12:21 |
We have the code over here.
我们在这里有代码。 |
12:23 |
And the last part is this part of the code.
最后一部分是这段代码。 |
12:25 |
If liquidity delta is less than 0, then this means that liquidity was removed.
如果流动性增量小于0,那么这意味着流动性被移除。 |
12:30 |
And if the boolean values were flipped,
如果布尔值被翻转, |
12:32 |
so this means that the liquidity was removed and the lower tick was flipped.
这意味着流动性被移除,并且下限刻度被翻转。 |
12:36 |
This means that this tick's liquidity is now equal to 0,
这意味着这个刻度的流动性现在等于0, |
12:39 |
so we can remove this tick.
所以我们可以移除这个刻度。 |
12:41 |
So say if flipped lower, then clear this tick.
所以说如果flipped lower,那么清除这个刻度。 |
12:46 |
Ticks.clear.tick.lower.
Ticks.clear.tick.lower。 |
12:49 |
And we'll do the same for the upper tick.
我们对上限刻度做同样的操作。 |
12:51 |
If flipped upper, then ticks.clear.tick.upper.
如果flipped upper,那么ticks.clear.tick.upper。 |
12:55 |
Okay, that completes the function update position for now.
好的,这暂时完成了函数更新位置。 |
12:59 |
Let's try compiling the contract.
让我们尝试编译合约。 |
13:01 |
I'll open my terminal and then type forge build.
我将打开我的终端,然后输入forge build。 |
13:05 |
And our contract compiled.
我们的合约编译成功。 |
13:07 |
In this video, we've completed the update function except for calculating the fees,
在这个视频中,我们完成了更新函数,除了计算费用, |
13:12 |
which will be the last part of the video series.
这将是视频系列的最后一部分。 |
13:15 |
Now, writing the code inside the update position,
现在,在更新位置中编写代码, |
13:18 |
we wrote some code inside ticks.update.
我们在ticks.update中写了一些代码。 |
13:21 |
And if we take a look at this function, ticks.update, we came across a term
如果我们查看这个函数ticks.update,我们遇到了一个术语 |
13:25 |
called liquidity.net.
叫做liquidity.net。 |
13:27 |
This is a variable that is used to track the current liquidity.
这是一个用于跟踪当前流动性的变量。 |
13:31 |
In the next few videos,
在接下来的几个视频中, |
13:32 |
I'll explain how liquidity.net is used to keep track of the current liquidity.
我将解释如何使用liquidity.net来跟踪当前流动性。 |
13:36 |
Thanks for watching.
感谢观看。 |
13:37 |
See you in the next video.
下个视频见。 |