WEBVTT

00:00.000 --> 00:04.860
My talk on Modeling Systemic Threat Using Mainnet Fork.

00:05.020 --> 00:09.360
And so, next one, who am I?

00:10.040 --> 00:15.580
I'm Martinet Li, a Research Engineer slash Security Auditor from QuantStamp.

00:15.580 --> 00:23.640
And since last year, I reviewed a lot of projects, especially in the DeFi space, as this particular space is booming.

00:24.060 --> 00:29.980
But I was also involved in some reviews on, you know, base layer chains.

00:30.000 --> 00:36.380
Like Eth2, Prism Implementation, and AvaLabs as well.

00:36.420 --> 00:40.800
And the girl beside me, that's my daughter, just by the way.

00:40.800 --> 00:42.240
And next one.

00:42.480 --> 00:53.340
So, what this presentation is about, I kind of want to be more like a light talk and perhaps interactive, so feel free to just shoot me any questions in between.

00:53.380 --> 00:59.080
But basically, what I wanted to share today is kind of the status quo on testing.

00:59.080 --> 01:04.020
From an auditor's point of view, and mainly focusing on composability.

01:04.600 --> 01:11.560
As projects integrate with others more closely, how are people right now testing their projects?

01:11.560 --> 01:14.580
And what I believe would be beneficial.

01:15.160 --> 01:22.180
I will also introduce my personal project on trying to improve testing with two simple examples here.

01:22.960 --> 01:24.920
So, next one.

01:25.720 --> 01:30.520
So, the main challenge here is the composability.

01:30.520 --> 01:32.420
So, what is composability?

01:32.560 --> 01:41.620
It is a feature of design wherein the various components of a system can be easily connected to form any number of satisfying results.

01:41.620 --> 01:44.280
That's from MakerDAO.

01:44.280 --> 01:51.380
And although blockchain projects have always been composable, you know, like it's always open API, right?

01:51.380 --> 02:03.280
Its power was really unleashed by the DeFi space, and especially the standardization of these token interfaces like ERC-20, ERC-721.

02:04.300 --> 02:13.220
In the beginning, we see most of projects focusing just building on their own ecosystem, pretty much independent from other projects.

02:13.220 --> 02:18.500
They issue these tokens just hoping other to use, maybe to trade.

02:18.500 --> 02:31.340
You know, but then with the use of these standardized interfaces, it allows like other projects to leverage like what, well, it allows projects to leverage one another, right?

02:31.340 --> 02:32.740
Kind of like Lego.

02:32.740 --> 02:35.500
So, that's the term money Lego.

02:35.920 --> 02:41.920
And easily connecting them together to create like so many different kinds of functionalities.

02:41.920 --> 02:48.480
Of course, exchanges are the first one, you know, just aggregates just using the interface and then sell them.

02:48.500 --> 02:53.940
They're just using the token, not really the internal functionality, right?

02:54.380 --> 03:04.880
Another piece which is important to this composability, which not necessarily fits into like this money Lego thing is the Oracle part.

03:04.880 --> 03:12.240
Oracle feeds us like maybe real world data and then allows us to use them on chain.

03:12.240 --> 03:17.660
So, it is also like an important piece in this composability, I would say.

03:18.220 --> 03:19.860
So, next one.

03:21.800 --> 03:25.580
So, composability is certainly a blessing.

03:25.580 --> 03:32.860
So, we see that there are so many interesting projects in the past few years that emerges from here, right?

03:32.860 --> 03:40.400
Pulled together as one example, it builds like no loss lottery on top of the compound protocol, right?

03:40.520 --> 03:45.200
So, as time goes by, like projects tend to grow more complex.

03:45.200 --> 03:50.280
One of the prime example recently would be the Yearn protocol, right?

03:50.280 --> 04:00.980
That helps user yield farming by putting together like Curve, AVI, Compound, MStable, and a lot of other protocols, right?

04:00.980 --> 04:09.980
I would say it's one of the amazing projects that full of creativity and demonstrate what can be done with this composability.

04:11.120 --> 04:12.800
Now, next.

04:13.600 --> 04:18.860
However, this composability is also a curse, right?

04:18.860 --> 04:26.660
So, we have already witnessed several attacks and one systematic failure that affected the whole DeFi community.

04:26.660 --> 04:38.740
And I'll just like bring up a simple example here, which is the first BZX attack, which involves a DYDX, Compound, BZX, Kyber, and Uniswap, right?

04:38.740 --> 04:53.740
It uses the DYDX, a flagship ability, and then borrow WBTC from Compound, uses BZX as a platform to short ETH in favor of WBTC.

04:53.740 --> 05:05.480
And in turn, because internally like Kyber and Uniswap was used in the BZX, it drove up the price of WBTC and Uniswap.

05:05.480 --> 05:11.580
And then the hacker was able to just dump the WBTC and profit from there.

05:11.580 --> 05:19.120
So, you see like this complexity is also opens a lot of like, you know, different kinds of attack.

05:19.440 --> 05:20.980
That's for one.

05:20.980 --> 05:22.660
And next.

05:24.760 --> 05:28.980
And we also see like in the black Thursday, right?

05:29.260 --> 05:35.320
Not sure if the graph is visible, but we probably all know, they grew up for 30%.

05:36.740 --> 05:44.520
At the same time, so MakerDAO price did not update for a while.

05:44.520 --> 05:46.420
So they do have like Oracle.

05:46.420 --> 05:51.820
But during that time, the gas price was extremely high.

05:51.880 --> 05:57.920
And thus the price was not able to update in real time.

05:57.920 --> 06:02.620
And when it updated, it triggered like a massive liquidation.

06:03.210 --> 06:10.420
In turn, this is one of the reasons why like, there are so many collateral were auctioned off for zero.

06:10.980 --> 06:17.440
So, part of this is because of the Oracle issue here.

06:18.140 --> 06:19.320
So, next.

06:21.160 --> 06:27.040
So, I would say composability is almost like a nightmare for developers.

06:27.040 --> 06:37.900
Repeatedly see this issue, like causes a lot of troubles for developers, especially when it comes to testing the project, right?

06:37.900 --> 06:44.260
Like, how should the developer ensure the project that they interface with are working as expected?

06:44.580 --> 06:48.880
And then how, like, this is already hard, right?

06:48.880 --> 06:57.300
And so, I don't really see anyone like testing extreme scenarios, like the ones that we would mention above.

06:58.220 --> 07:00.660
So, let's go on to the next.

07:02.280 --> 07:06.980
So, the status quo on testing, kind of doing a review.

07:07.600 --> 07:18.160
What we see as auditors, typically, you know, if they have tests, they have unit tests, they have functional tests, like for internal protocol.

07:18.780 --> 07:28.180
But when it comes to testing the integration points with other projects, what we see, you know, some variety there.

07:28.300 --> 07:37.920
For the simple ones, if the external project is really simple, then you can deploy the external projects locally, you know, just in the ganache.

07:37.920 --> 07:40.300
This is possible when it's small, right?

07:40.300 --> 07:46.020
But it's impossible if the external project is complicated.

07:46.020 --> 07:50.880
Just imagine, like, you're deploying the whole MakerDAO system.

07:50.880 --> 07:52.860
Well, that's going to be a nightmare.

07:53.820 --> 07:54.740
Next.

07:55.280 --> 08:02.140
And so, there's the second option, which is mocking the external protocol, right?

08:02.140 --> 08:08.160
A developer has to understand what the external contract would do and mock the behavior accordingly.

08:09.200 --> 08:20.940
Oftentimes, developers will simplify these logic to, you know, to not really implement everything in the protocol, but just the behavior.

08:20.940 --> 08:27.300
And so, there are possible discrepancies between the mocked contract and the real behavior.

08:27.300 --> 08:30.800
And that actually presents a potential risk.

08:31.340 --> 08:36.640
Now, next on, we have testing on testnet, right?

08:36.640 --> 08:41.120
If you're interfacing with just one project, it kind of works.

08:41.120 --> 08:45.980
Although, it's still tedious to get all the test tokens, testnet tokens, and, like, Ether.

08:45.980 --> 08:47.900
You need the faucet for that.

08:48.020 --> 09:00.440
But if you're building a project that interfaces with different projects, then you can see on the right-hand side, like, this is how, you know, projects on the testnet would look like.

09:00.440 --> 09:03.620
Like, MakerDAO, they probably have their own testnet.

09:03.620 --> 09:09.900
But for sure, I know Aave and Compound, they use, like, different dymocks on the testnet.

09:09.900 --> 09:26.920
And so, if you're testing, if you are writing a project that interfaces with both Aave and Compound and want to use dye in between, this is simply different, you know, from the structure in mainnet.

09:27.140 --> 09:29.000
Now, next.

09:29.960 --> 09:35.060
Ah, well, here we have testing on mainnet.

09:35.060 --> 09:38.060
And needless to say, this is super costly.

09:38.420 --> 09:45.100
Typically, it only allows functional and high-level manual testing, you know.

09:45.100 --> 09:52.140
And so, among all these, I would say the most common ones are mocking.

09:52.940 --> 09:58.120
But testing on testnet do exist, but typically done, like, not very extensively.

09:59.000 --> 10:08.700
Because developers, like, oftentimes find, you know, fetching those resources very, very troublesome, right?

10:08.700 --> 10:15.480
And so, I have personally seen projects that did both the mock and testing on testnet.

10:15.480 --> 10:22.320
So that's, you know, they are, you can see that they're trying their best, but still missed to test the profit sharing.

10:22.320 --> 10:30.300
Because that requires some understanding of the underlying protocol and how they would behave.

10:30.300 --> 10:32.280
So they missed that in the mock.

10:32.860 --> 10:44.380
And then on the testnet, because it was kind of like one-shot testing, it doesn't really wait for the time and wait for the profit to accrue.

10:44.380 --> 10:47.300
So, like, they missed the profit sharing part.

10:47.400 --> 10:50.420
And we were able to locate that issue, luckily.

10:51.080 --> 11:06.660
After that, I sort of see this as this lack of testing facility that helps, you know, testing, like, composability thing is a huge security issue for the whole ecosystem.

11:07.940 --> 11:08.920
Next.

11:11.120 --> 11:19.260
And so, with the standard tool, actually, I do, there are one option that I would say it's quite nice.

11:20.420 --> 11:24.340
I do recommend, like, testing under this mainnet fork.

11:24.340 --> 11:35.240
And Ganache provides this fork option, which, surprisingly, I haven't seen any project uses this to test external library.

11:35.700 --> 11:41.120
And that's probably because of my side note right there.

11:41.420 --> 11:44.720
The fork does have some bug.

11:45.280 --> 11:58.800
You know, when you use Uniswap, you probably, you'll face some weird re-entrancy error, like reverts, but you never did a re-entrancy there.

11:59.040 --> 12:03.140
So, but there is a pull request, but I don't think a lot of people know that.

12:03.140 --> 12:06.740
I think that's probably one of the reasons that this is not used.

12:06.740 --> 12:13.920
But if this is used and fixed, then I see this is actually pretty nice.

12:14.520 --> 12:20.360
Projects interconnect with each other the same way as mainnet, because it's the mainnet fork.

12:20.360 --> 12:24.020
There's, of course, no cost, because it's a local Ganache.

12:24.140 --> 12:29.820
And then huge amount of ethers when starting up the local blockchain, as always.

12:30.500 --> 12:35.160
And, you know, Ganache also allows you to sign transaction as other accounts.

12:35.160 --> 12:39.120
So you can be the whale, you know, anytime.

12:39.120 --> 12:41.120
So this is already pretty nice.

12:41.830 --> 12:42.610
Next.

12:43.480 --> 12:52.220
So with this, we can already start to model a systemic threat, which is the whale, right?

12:52.220 --> 12:59.620
For example, to be a die whale here, well, you can use an unlock account.

13:00.060 --> 13:13.560
You find some die whale on the mainnet and, you know, just write his address down, unlock his address on your local Ganache and use that to test.

13:13.600 --> 13:14.800
So that's good.

13:14.800 --> 13:23.780
The downside is that, well, if the whale just transfers his die to other places, then, you know, this test doesn't work anymore.

13:23.780 --> 13:26.280
You need to find another die whale.

13:26.660 --> 13:32.180
So, you know, not really reliable as test, I would say.

13:33.500 --> 13:39.380
The other two paths that you can do is that you can, of course, mint die on MakerDAO.

13:39.380 --> 13:46.360
However, that requires you to, you know, you already have that huge amount of ethers, so you can definitely do that, right?

13:46.360 --> 13:54.020
But you have to know how to open vault, lock up collateral and use that to mint die.

13:54.040 --> 13:59.120
But in the end, what you really want is just increasing your balance in the die.

13:59.120 --> 14:02.700
You know, it's pretty tedious and going through all that.

14:02.700 --> 14:04.860
And same for buying die on DEX.

14:04.860 --> 14:11.240
If you want to do that, you need to know Uniswap's interface, perhaps, and how to interact with them.

14:11.520 --> 14:16.360
So it's not as convenient.

14:17.000 --> 14:18.160
So, next.

14:20.720 --> 14:24.800
Yeah, and still, like, some risk remains very hard to model.

14:25.470 --> 14:33.780
Like, if modeling a risk involves changing the price feed on MakerDAO or Uniswap v2, that may be a problem.

14:33.940 --> 14:53.520
And then, let's say, if you want to model what would happen on your platform or your smart contract when you experience an oracle attack, like, for example, you're using Uniswap and you're also using Chainlink as your oracle.

14:53.520 --> 15:01.120
What would happen if there is a mismatch on my protocol, right?

15:01.120 --> 15:02.620
Can I model that?

15:03.180 --> 15:07.760
And then, you know, seeing the BZX attack, that's pretty sophisticated.

15:08.180 --> 15:12.600
It might be very hard to come up with that sort of scenarios.

15:12.600 --> 15:24.040
And so, one thing that you might want to do is just assume that there could be a mismatch in the oracle price, then what would happen, right?

15:24.040 --> 15:25.420
That's much easier.

15:25.420 --> 15:33.060
But in this mainnet fork, you cannot do that because you still have to follow all the blockchain rules, right?

15:33.060 --> 15:42.580
And in general, if modeling requires, like, changing a variable that is not directly settable by an externally owned account, this is challenging.

15:43.480 --> 15:53.860
So, the question, next one, is what if we could ignore code as law, you know, on the local blockchain?

15:53.860 --> 16:00.380
And what if, like, can we change the storage directly without any permission?

16:00.820 --> 16:02.180
Next one.

16:03.500 --> 16:17.580
So, I kind of went on this direction and digged into the ganache because since this is the testing environment that most of the people are using, I decided to dig into this one and see if this can be accomplished.

16:17.680 --> 16:23.820
And so, ganache itself, it kind of looks like this, you know, like the related part.

16:23.820 --> 16:30.540
It has WS server, HTTP server, and it connects to this get API module that it has internally.

16:30.540 --> 16:40.980
This get API module controls the state manager, and it's supported by a VM, which is the Ethereum JS VM.

16:41.600 --> 16:44.980
So, next.

16:47.120 --> 17:05.440
And so, within this ganache, this state manager, you know, within this VM, then I found that in the VM state manager, there's actually a free function that is very useful for us, which is the put account, put contract code, put contract storage.

17:05.440 --> 17:15.040
By using these, essentially, you can directly modify the storage and the state of the local ganache.

17:15.140 --> 17:23.820
So, what typically was done is that you still go through ganache and send transaction to ganache.

17:23.820 --> 17:34.620
So, what I tried to do was to open up a backdoor, if you may, and say that, hey, I don't want to verify my transaction.

17:34.620 --> 17:38.620
I just directly want to modify my storage right there.

17:38.880 --> 17:44.100
So, that's the root of my project.

17:44.100 --> 17:46.160
And so, next one.

17:47.640 --> 17:53.240
So, after some development, like, this is my project, which I call Godmode for Test.

17:53.240 --> 17:55.920
It basically consists of three parts.

17:56.220 --> 18:00.920
The project itself is still in, like, very early stage and still needs a lot of work.

18:00.920 --> 18:10.560
It already works, and I personally use it for development, especially when it's come to DeFi projects.

18:10.560 --> 18:14.500
So, what I built consists of three pieces.

18:14.500 --> 18:18.520
The first one is this ganache core.

18:18.520 --> 18:27.900
So, this modified ganache core allows us to ignore the blockchain log and just directly modify the storage, as previously stated.

18:27.900 --> 18:37.100
And then, on top of that, I created a wrapper JavaScript library that you can integrate into the Truffle framework.

18:37.120 --> 18:46.900
So, you know, all the familiar tools that we use and leverage the Solidity contract as sort of an API.

18:46.900 --> 18:52.260
I think it's easier to understand how to modify the storage of the blockchain.

18:52.820 --> 18:55.680
And there's some set of precompiled contracts.

18:56.560 --> 19:00.800
So, what the precompiled contracts would do...

19:01.260 --> 19:01.920
next, please...

19:03.500 --> 19:10.740
is, you know, I want to provide some easy-to-set-up scenarios for the developers.

19:10.740 --> 19:28.580
For example, to mint Dai, you don't have to think about finding that whale and, you know, worry about the whale will transfer it away and the test won't work anymore, or worry about all the vault, you know, all the original mint Dai process.

19:28.580 --> 19:40.140
Now, what you need to do is just call this function call and then it will give Bob, you know, 10,000 Dai, which is great.

19:40.740 --> 19:41.900
Next.

19:44.060 --> 19:46.820
And in a more general sense...

19:47.580 --> 19:54.020
So, this is a general API that I provide that you can basically craft...

19:55.960 --> 20:00.720
use this to modify, like, arbitrary contract storage.

20:00.720 --> 20:06.920
And so, it might not be very clear just by seeing this.

20:06.920 --> 20:10.100
And so, I'll demonstrate a few examples.

20:10.960 --> 20:15.660
I'm happy that I have had the backup of, like, kind of all the screenshots.

20:16.380 --> 20:18.320
And so, yeah, we'll...

20:18.320 --> 20:19.540
I kind of...

20:19.540 --> 20:24.100
I will kind of walk you through, like, all the screenshots on doing these things.

20:24.660 --> 20:25.960
So, yeah.

20:25.960 --> 20:27.980
So, next one.

20:28.140 --> 20:42.780
So, we'll go through, like, the first example, which is using that general API and use it to mint Dai, you know, like, the one that I already had in the library.

20:42.780 --> 20:45.640
But right now, I just wanted to show you how this could be done.

20:45.660 --> 20:53.360
And so, the first step would be you go and find Dai's source code and mainnet address.

20:53.360 --> 20:56.620
And, of course, both are available on Etherscan.

20:56.620 --> 20:59.320
So, you go there, copy it down.

20:59.320 --> 21:05.100
I'm assuming that we're using, like, Truffle project framework here.

21:05.100 --> 21:10.140
So, we just store the Dai source code under the contracts folder.

21:10.780 --> 21:11.900
Next one.

21:15.000 --> 21:22.360
And so, the following step is we clone that Dai contract, you know, rename it.

21:22.360 --> 21:26.960
So, now we would have, like, let's say two contracts.

21:26.960 --> 21:27.940
One is Dai.

21:27.940 --> 21:31.260
Let's say the other one is called gmDai.

21:32.500 --> 21:36.080
And we modify the mint function.

21:36.080 --> 21:39.140
So, how we modify it, it's really simple.

21:39.140 --> 21:45.980
The reason that we cannot mint Dai is it was authorized.

21:45.980 --> 21:47.880
Like , it is controlled.

21:48.600 --> 21:55.420
There's a requirement statement that prevents us from going in, which is this modifier auth, right?

21:55.420 --> 21:59.540
So, what we can do is just to remove that auth.

21:59.540 --> 22:05.380
And that allows anyone to call this mint.

22:05.380 --> 22:10.040
So, you know, that's essentially how it's done.

22:10.180 --> 22:10.940
Next.

22:14.080 --> 22:20.460
And so, in the normal test, and this is how we would write it.

22:20.740 --> 22:30.540
So, we have, we would require both artifacts, include both artifacts into the test, which is the Dai and gmDai.

22:30.540 --> 22:37.500
So, you recognize gmDai is the one that we just modified and removed the modifier, right?

22:38.160 --> 22:51.600
And, you know, and like all other stuff are pretty much just set up, basic setup, like, you know, talking to the Godmode Ganache and all that.

22:51.600 --> 23:01.740
But the real essential part is the part that I, you know, had with the red square or rectangle, whatever, that's the executeAs.

23:01.740 --> 23:07.580
So, what you do here is actually you're executing the Dai contract.

23:07.580 --> 23:11.960
So, you see this Dai contract is just like two lines above.

23:11.960 --> 23:15.860
It's, it was like a way to Dai at this address.

23:15.860 --> 23:20.880
And that's the address of the main net Dai address, right?

23:20.880 --> 23:31.440
And so, I execute this Dai contract as if it is the modified contract.

23:31.740 --> 23:38.800
So, I'm actually just executing, you can think of it that this way.

23:38.800 --> 23:43.560
So, I am modifying the storage of Dai contract.

23:43.560 --> 23:51.840
But according to the rules set by this gmDai artifact or contract.

23:51.840 --> 23:58.760
And so, here, essentially, I'm just calling mint from the gmDai contract.

23:58.760 --> 24:02.600
Then I say, give Alice this amount of Dai.

24:02.740 --> 24:05.140
And the next line is assertion.

24:05.280 --> 24:10.160
And so, this is, yeah, this is basically how it works.

24:11.420 --> 24:12.760
Next one.

24:15.360 --> 24:19.400
Now, so, that's the, that's just minting Dai.

24:19.400 --> 24:25.060
And so, as a second example, I'll show you how to modify to make a DAO price feed.

24:25.060 --> 24:36.260
Now, this is an essential step for modeling this systemic threat, like, you know, oracle attacks and all of that.

24:36.260 --> 24:47.460
Because what you want to do is to have, like, maybe two oracles report different values, right?

24:47.460 --> 24:52.100
So, you want to read and perhaps change to make one of the oracles price feed.

24:52.100 --> 24:53.980
Here, I chose my DAO.

24:53.980 --> 24:59.360
And, of course, you just Google and find out where the maker DAO is getting their price.

25:00.300 --> 25:05.160
And so, this is the address that I found on their page.

25:05.200 --> 25:10.540
And then you just go to that ether scan the same way we did as Dai.

25:10.540 --> 25:12.540
And then copy the source code.

25:13.400 --> 25:14.680
Next one.

25:17.590 --> 25:22.270
Yeah, and, you know, this is still a little bit technical.

25:22.270 --> 25:25.970
You have to understand kind of how it works.

25:25.970 --> 25:29.070
But luckily, most of the oracles are pretty simple.

25:29.070 --> 25:31.590
They're basically reporting what they have.

25:31.590 --> 25:33.310
Maybe they have something else.

25:33.310 --> 25:38.790
Like, in this maker DAO price feed, this OSM module is their oracle.

25:38.790 --> 25:42.870
I think it's oracle security module or something like that.

25:43.210 --> 25:46.870
So, OSM module basically has an example.

25:46.870 --> 25:49.770
Hey, OSM peak is getting the current value.

25:49.770 --> 25:52.670
Or OSM read is getting the current value or fail.

25:52.670 --> 25:56.330
And so, you go and look at the source code of OSM.

25:56.330 --> 26:04.290
And you find out that, ah, it is actually returning the value from this curr.val, right?

26:04.290 --> 26:08.210
So, this is where the current value is storing.

26:08.990 --> 26:14.590
And so, what we want to do is basically just read this one.

26:14.590 --> 26:20.190
And, you know, and perhaps modify it.

26:20.190 --> 26:31.470
And so, the reason I say read is that if you later take a look at the OSM contract, you see, well, you see right here, actually.

26:31.470 --> 26:34.330
There's a modifier called tall.

26:34.330 --> 26:42.510
And that prevents any user, like, external contracts from using, from reading the value here.

26:42.510 --> 26:49.450
But if we want to just use, just inspect this value, we can actually do that.

26:50.290 --> 26:51.170
But, okay.

26:51.170 --> 26:52.450
So, next one.

26:56.560 --> 27:02.660
And so, yeah, kind of same way we did on the die to GM die.

27:02.660 --> 27:12.520
So, we modify the clone OSM module, add these two functions and event.

27:12.520 --> 27:21.100
The reason I do event is that, unfortunately, right now, it doesn't read.

27:21.440 --> 27:28.880
So , this execute as cannot just read a function.

27:28.880 --> 27:31.500
You know, like, it will always do a state change.

27:31.500 --> 27:35.960
So, if you do a view function, then it will revert on that.

27:35.960 --> 27:37.960
So, this is kind of a workaround.

27:37.960 --> 27:41.740
But nevertheless, you can still get the value this way.

27:41.740 --> 27:47.440
And then, the next one is pretty simple, which is just setting that current value.

27:47.440 --> 27:47.540
Right ?

27:47.540 --> 27:52.300
So, set curve val and curve dot val equals to the new value that we have.

27:52.860 --> 27:54.060
Next one.

27:56.620 --> 28:03.760
And so, with this, you know, we can just write test to check the behavior.

28:04.700 --> 28:19.840
Similar way as we would say that this OSM contract is the OSM at, you know, the original address that this contract were placed.

28:19.980 --> 28:26.580
And then, the next two lines, this transaction, weird transaction thing is reading from the logs.

28:26.580 --> 28:28.560
Basically, reading from the events.

28:28.560 --> 28:33.640
And then, reading the current value out of that event.

28:35.160 --> 28:39.960
So, in the middle, there's this await got node execute.

28:39.960 --> 28:41.980
So, here, again, it's the same thing.

28:41.980 --> 28:48.300
We're executing this OSM contract as our modified contract.

28:48.300 --> 28:54.160
And now, you see that this set curve val is a function that we added.

28:54.160 --> 28:57.820
It's not anywhere in the original contract.

28:57.820 --> 29:00.000
And we just added that part.

29:00.000 --> 29:06.160
But now, this modified ganache will be able to run this thing.

29:06.320 --> 29:13.080
And then, it will just set the curve that val into this new function.

29:13.080 --> 29:14.100
Oh, sorry, value.

29:14.660 --> 29:19.980
And I just printed out, print the value again to see what's there.

29:21.560 --> 29:23.000
Next one.

29:24.420 --> 29:27.860
So, now, yeah, this is kind of the result.

29:27.860 --> 29:38.080
You'll see that the original value is this, basically, 387 USD, right?

29:38.080 --> 29:43.880
And then, I just set it to some number that I just thought set there.

29:44.120 --> 29:49.340
So, now, you are able to change the make and dial price feed with this thing.

29:51.980 --> 29:54.140
Yeah, so, next one.

29:55.620 --> 30:03.440
So, some downside of this tool is that mainnet fork can be buggy for the ganache.

30:03.900 --> 30:08.800
So, the fix that I have there in the side node is not official.

30:09.740 --> 30:13.120
So, you know, sometimes, there are some bugs there.

30:13.220 --> 30:21.460
And the second one, you kind of already saw that we cannot create view function and return properly yet.

30:21.460 --> 30:22.900
So, I'm still working on that.

30:24.880 --> 30:28.300
And, of course, this is a local ganache.

30:28.300 --> 30:32.320
So, you cannot simulate how others would behave.

30:32.320 --> 30:45.620
You know, it's not like a simulation that you can see all, like, with this new values, how are people going to behave with the new incentive and stuff, right?

30:45.620 --> 30:48.380
So, you're alone in this local blockchain.

30:48.380 --> 30:51.600
That's kind of an inherent limitation here.

30:52.540 --> 30:59.440
And fourth is this arbitrary modify storage is sometimes too powerful.

30:59.440 --> 31:05.400
Because, you know, it can get you to state that are just not possible to reach.

31:06.140 --> 31:13.480
So , you have to be careful about and thinking about what kind of scenarios you want to craft.

31:13.480 --> 31:15.420
And if that is a reasonable scenario.

31:15.420 --> 31:24.960
Because before this tool, you have to think of ways to get to a state.

31:24.960 --> 31:26.910
And then you can start testing.

31:27.420 --> 31:31.420
Now, with this tool, you can get to any state directly.

31:31.420 --> 31:36.070
But whether that state makes sense or not, that's another question.

31:36.460 --> 31:41.560
So, that's another problem that we have to take care and think about.

31:41.820 --> 31:42.670
Yeah.

31:43.420 --> 31:45.400
And so, next one.

31:47.400 --> 31:56.980
Kind of a conclusion is that DeFi composability is currently both a blessing and a curse.

31:57.100 --> 32:04.980
I hope that with more testing facilities, we can turn it into a pure bliss.

32:05.680 --> 32:14.880
And as of right now, as I've said, I don't see a lot of testing on even the integration side.

32:14.880 --> 32:20.200
Let alone testing extreme scenarios to prevent systemic threats.

32:21.320 --> 32:33.200
Like, you know, I've really never seen people testing how systems would react if an Oracle attack is to happen, you know, modeling these different threats.

32:33.260 --> 32:33.780
Right?

32:33.780 --> 32:37.720
But this is mainly because there's no...

32:38.520 --> 32:42.240
Well, there are not a lot of tools that support this.

32:42.300 --> 32:43.260
Right?

32:43.260 --> 32:47.840
And so, I believe there's still a lot of space to improve in testing.

32:47.840 --> 32:51.260
Especially in terms of this composability thing.

32:51.900 --> 32:54.620
And I think we need...

32:55.500 --> 32:57.960
This presentation is almost like...

32:58.840 --> 33:04.080
I would treat it like an open invitation for everyone to kind of work on this area.

33:04.420 --> 33:19.060
I believe we need to work together to help secure all these blockchain projects and make this, you know, make the testing facilities better and make the composability not a headache anymore.

33:19.320 --> 33:20.060
Yeah.

33:20.060 --> 33:21.320
And that's it.

33:21.320 --> 33:23.480
Thank you for your time.

33:23.480 --> 33:24.640
Great presentation.

33:31.830 --> 33:32.990
All right.

33:32.990 --> 33:34.910
Any questions?

33:38.410 --> 33:40.110
Ah, I see.

33:40.110 --> 33:47.150
Are there limitations between forking mainnet from full versus archive nodes?

33:47.150 --> 33:51.530
Ah, it depends.

33:51.530 --> 33:59.350
So , I actually just used Infura, not even the full node.

33:59.350 --> 34:02.130
Oh, Infura is the full node, right?

34:02.130 --> 34:04.550
Yeah, but I've just been using Infura.

34:04.550 --> 34:12.670
And if you just care about how it's going to react at its current stage, I think that's fine.

34:13.390 --> 34:22.910
After like 30 minutes, then your test would start failing, and it will say that, hey, you know, you don't have access to archive nodes.

34:23.790 --> 34:26.180
Then that would start failing.

34:27.390 --> 34:41.590
But, you know, just for the purpose of doing unit tests on mainnet fork, especially for the integration part, I think you don't really need an archive node, to be honest.

34:42.080 --> 34:42.810
Yeah,

34:48.880 --> 34:51.040
no problem.

34:51.040 --> 34:52.220
My pleasure.

34:54.200 --> 35:03.460
Ah, yes, let me paste my GitHub repository into the chat.

35:03.860 --> 35:11.520
I have to warn everyone that this is like a very, very, you know, initial work.

35:11.520 --> 35:14.060
It works, but it's very ugly.

35:14.860 --> 35:24.240
I'm not particularly proud about the code quality, but I am pretty happy about the result that it can get me, though.

35:24.240 --> 35:26.160
So I'm happy to share.

35:35.400 --> 35:38.760
All right, any other questions?

35:38.780 --> 35:40.360
Thank you, Miko.

35:53.150 --> 35:54.650
Thank you.

35:54.650 --> 35:56.230
Thank you.

35:56.230 --> 35:59.450
Do we have other questions, like in Twitch?

