[00:00.000 --> 00:04.860] My talk on Modeling Systemic Threat Using Mainnet Fork. [00:05.020 --> 00:12.660] And so, next one, who am I? I'm Martinet Li, a Research Engineer [00:12.660 --> 00:18.620] slash Security Auditor from QuantStamp. And since last year, I reviewed a lot of projects, [00:18.620 --> 00:23.640] 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:45.520] And next one. So, what this presentation is about, [00:45.520 --> 00:49.760] I kind of want to be more like a light talk and perhaps interactive, [00:49.760 --> 00:53.340] 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:08.380] As projects integrate with others more closely, [01:08.380 --> 01:14.580] how are people right now testing their projects? And what I believe would be beneficial. [01:15.160 --> 01:19.220] I will also introduce my personal project on trying to improve testing [01:19.220 --> 01:24.920] with two simple examples here. So, next one. [01:25.720 --> 01:30.520] So, the main challenge here is the composability. [01:30.520 --> 01:35.020] So, what is composability? It is a feature of design wherein [01:35.020 --> 01:38.840] the various components of a system can be easily connected [01:38.840 --> 01:44.280] to form any number of satisfying results. That's from MakerDAO. [01:44.280 --> 01:48.560] And although blockchain projects have always been composable, [01:48.560 --> 01:51.380] you know, like it's always open API, right? [01:51.380 --> 01:55.380] Its power was really unleashed by the DeFi space, [01:55.380 --> 02:03.280] and especially the standardization of these token interfaces like ERC-20, ERC-721. [02:04.300 --> 02:10.160] In the beginning, we see most of projects focusing just building on their own ecosystem, [02:10.400 --> 02:13.220] 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:25.040] You know, but then with the use of these standardized interfaces, [02:25.040 --> 02:28.600] it allows like other projects to leverage like what, [02:28.600 --> 02:31.340] well, it allows projects to leverage one another, right? [02:31.340 --> 02:35.500] Kind of like Lego. 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:44.820] Of course, exchanges are the first one, you know, [02:44.820 --> 02:48.480] 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 --> 02:58.560] Another piece which is important to this composability, [02:58.560 --> 03:04.880] 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:28.680] So, we see that there are so many interesting projects [03:28.680 --> 03:32.860] in the past few years that emerges from here, right? [03:32.860 --> 03:35.500] Pulled together as one example, [03:35.500 --> 03:40.400] 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 --> 03:58.180] That helps user yield farming by putting together like Curve, AVI, Compound, MStable, [03:58.180 --> 04:00.980] and a lot of other protocols, right? [04:00.980 --> 04:05.440] I would say it's one of the amazing projects that full of creativity [04:05.440 --> 04:09.980] 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:23.300] So, we have already witnessed several attacks and one systematic failure [04:23.910 --> 04:26.660] that affected the whole DeFi community. [04:26.660 --> 04:31.840] And I'll just like bring up a simple example here, which is the first BZX attack, [04:31.840 --> 04:38.740] which involves a DYDX, Compound, BZX, Kyber, and Uniswap, right? [04:38.740 --> 04:45.600] It uses the DYDX, a flagship ability, and then borrow WBTC from Compound, [04:46.280 --> 04:53.740] uses BZX as a platform to short ETH in favor of WBTC. [04:53.740 --> 04:59.940] And in turn, because internally like Kyber and Uniswap was used in the BZX, [04:59.940 --> 05:05.480] 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:17.400] So, you see like this complexity is also opens a lot of like, [05:17.400 --> 05:20.980] you know, different kinds of attack. 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:34.200] Not sure if the graph is visible, but we probably all know, [05:34.200 --> 05:35.320] 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:06.220] In turn, this is one of the reasons why like, [06:06.220 --> 06:10.420] 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:33.920] Repeatedly see this issue, like causes a lot of troubles for developers, [06:33.920 --> 06:37.900] especially when it comes to testing the project, right? [06:37.900 --> 06:40.920] Like, how should the developer ensure the project [06:40.920 --> 06:44.260] 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:53.740] And so, I don't really see anyone like testing extreme scenarios, [06:53.740 --> 06:57.300] 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:11.380] What we see as auditors, typically, you know, [07:11.380 --> 07:14.360] if they have tests, they have unit tests, [07:14.360 --> 07:18.160] they have functional tests, like for internal protocol. [07:18.780 --> 07:24.500] But when it comes to testing the integration points with other projects, [07:24.500 --> 07:28.180] what we see, you know, some variety there. [07:28.300 --> 07:32.900] For the simple ones, if the external project is really simple, [07:32.900 --> 07:37.920] 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:06.020] A developer has to understand what the external contract would do [08:06.020 --> 08:08.160] and mock the behavior accordingly. [08:09.200 --> 08:14.920] Oftentimes, developers will simplify these logic to, you know, [08:14.920 --> 08:20.940] 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 --> 08:52.120] But if you're building a project that interfaces with different projects, [08:52.120 --> 08:58.040] then you can see on the right-hand side, like, this is how, you know, [08:58.040 --> 09:00.440] 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:14.940] And so, if you're testing, if you are writing a project [09:14.940 --> 09:20.020] that interfaces with both Aave and Compound and want to use dye in between, [09:20.020 --> 09:26.920] 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:03.740] Because developers, like, oftentimes find, you know, [10:03.740 --> 10:08.700] 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:19.720] So that's, you know, they are, you can see that they're trying their best, [10:19.720 --> 10:22.320] but still missed to test the profit sharing. [10:22.320 --> 10:28.500] Because that requires some understanding of the underlying protocol [10:28.500 --> 10:30.300] and how they would behave. [10:30.300 --> 10:32.280] So they missed that in the mock. [10:32.860 --> 10:39.060] And then on the testnet, because it was kind of like one-shot testing, [10:39.060 --> 10:44.380] 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 --> 10:57.620] After that, I sort of see this as this lack of testing facility [10:57.620 --> 11:01.700] that helps, you know, testing, like, composability thing [11:02.760 --> 11:06.660] is a huge security issue for the whole ecosystem. [11:07.940 --> 11:08.920] Next. [11:11.120 --> 11:14.940] And so, with the standard tool, actually, I do, [11:14.940 --> 11:19.260] 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:27.600] And Ganache provides this fork option, [11:28.620 --> 11:35.240] 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:48.440] You know, when you use Uniswap, you probably, [11:50.320 --> 11:55.680] you'll face some weird re-entrancy error, like reverts, [11:55.680 --> 11:58.800] 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:18.420] Projects interconnect with each other the same way as mainnet, [12:18.420 --> 12:20.360] 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:08.300] You find some die whale on the mainnet and, you know, just write his address down, [13:09.060 --> 13:13.560] 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:20.560] The downside is that, well, if the whale just transfers his die to other places, [13:20.560 --> 13:23.780] 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:44.560] However, that requires you to, you know, you already have that huge amount of ethers, [13:44.560 --> 13:46.360] 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:31.840] Like, if modeling a risk involves changing the price feed on MakerDAO or Uniswap v2, [14:31.840 --> 14:33.780] that may be a problem. [14:33.940 --> 14:42.280] And then, let's say, if you want to model what would happen on your platform or your smart [14:42.280 --> 14:48.840] contract when you experience an oracle attack, like, for example, you're using Uniswap and [14:48.840 --> 14:53.520] 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:21.640] And so, one thing that you might want to do is just assume that there could be a mismatch in [15:21.640 --> 15:24.040] the oracle price, then what would happen, right? [15:24.040 --> 15:25.420] That's much easier. [15:25.420 --> 15:31.960] But in this mainnet fork, you cannot do that because you still have to follow all the blockchain [15:31.960 --> 15:33.060] rules, right? [15:33.060 --> 15:39.140] And in general, if modeling requires, like, changing a variable that is not directly settable [15:39.140 --> 15:42.580] by an externally owned account, this is challenging. [15:43.480 --> 15:53.240] So, the question, next one, is what if we could ignore code as law, you know, on the local [15:53.240 --> 15:53.860] 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:10.320] So, I kind of went on this direction and digged into the ganache because since this is the [16:10.320 --> 16:15.240] testing environment that most of the people are using, I decided to dig into this one and [16:15.240 --> 16:17.580] 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:38.400] This get API module controls the state manager, and it's supported by a VM, which is the [16:38.400 --> 16:40.980] Ethereum JS VM. [16:41.600 --> 16:44.980] So, next. [16:47.120 --> 16:53.800] And so, within this ganache, this state manager, you know, within this VM, then I found that [16:53.800 --> 17:02.120] in the VM state manager, there's actually a free function that is very useful for us, which is [17:02.120 --> 17:05.440] the put account, put contract code, put contract storage. [17:05.440 --> 17:13.920] By using these, essentially, you can directly modify the storage and the state of the local [17:13.920 --> 17:15.040] 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:32.880] So, what I tried to do was to open up a backdoor, if you may, and say that, hey, I don't want [17:32.880 --> 17:34.620] 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:08.800] It already works, and I personally use it for development, especially when it's come to [18:08.800 --> 18:10.560] 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:24.680] So, this modified ganache core allows us to ignore the blockchain log and just directly [18:24.680 --> 18:27.900] modify the storage, as previously stated. [18:27.900 --> 18:35.140] And then, on top of that, I created a wrapper JavaScript library that you can integrate [18:35.140 --> 18:37.100] into the Truffle framework. [18:37.120 --> 18:45.520] So, you know, all the familiar tools that we use and leverage the Solidity contract as [18:45.520 --> 18:46.900] 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:18.260] For example, to mint Dai, you don't have to think about finding that whale and, you know, [19:18.260 --> 19:22.580] worry about the whale will transfer it away and the test won't work anymore, or worry [19:22.580 --> 19:28.580] about all the vault, you know, all the original mint Dai process. [19:28.580 --> 19:37.000] Now, what you need to do is just call this function call and then it will give Bob, you [19:37.000 --> 19:40.140] 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:36.000] So, we'll go through, like, the first example, which is using that general API and use it [20:36.000 --> 20:42.780] 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:28.280] So, we have, we would require both artifacts, include both artifacts into the test, [22:28.280 --> 22:30.540] 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:45.200] And, you know, and like all other stuff are pretty much just set up, basic setup, [22:45.200 --> 22:51.600] like, you know, talking to the Godmode Ganache and all that. [22:51.600 --> 22:59.080] But the real essential part is the part that I, you know, had with the red square or rectangle, [22:59.080 --> 23:01.740] 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:33.500] Now, this is an essential step for modeling this systemic threat, like, you know, [24:33.500 --> 24:36.260] 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:28.590] And so, the reason I say read is that if you later take a look at the OSM contract, [26:28.590 --> 26:31.470] 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:12.920] Similar way as we would say that this OSM contract is the OSM at, you know, [28:12.920 --> 28:19.840] 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:19.980] And the second one, you kind of already saw that we cannot create view function and return [30:19.980 --> 30:21.460] 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:40.740] You know, it's not like a simulation that you can see all, like, with this new values, [30:40.740 --> 30:45.620] 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:28.220] Like, you know, I've really never seen people testing how systems would react [32:28.220 --> 32:33.200] 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:09.700] I believe we need to work together to help secure all these blockchain projects [33:10.180 --> 33:14.780] and make this, you know, make the testing facilities better [33:14.780 --> 33:19.060] 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:17.770] After like 30 minutes, then your test would start failing, [34:17.770 --> 34:22.910] 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:34.530] But, you know, just for the purpose of doing unit tests on mainnet fork, [34:34.530 --> 34:36.330] especially for the integration part, [34:36.330 --> 34:41.590] I think you don't really need an archive node, to be honest. [34:42.080 --> 34:51.040] Yeah, 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:19.760] I'm not particularly proud about the code quality, [35:19.760 --> 35:24.240] 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?