1 00:00:00,000 --> 00:00:04,860 My talk on Modeling Systemic Threat Using Mainnet Fork. 2 00:00:05,020 --> 00:00:09,360 And so, next one, who am I? 3 00:00:10,040 --> 00:00:15,580 I'm Martinet Li, a Research Engineer slash Security Auditor from QuantStamp. 4 00:00:15,580 --> 00:00:23,640 And since last year, I reviewed a lot of projects, especially in the DeFi space, as this particular space is booming. 5 00:00:24,060 --> 00:00:29,980 But I was also involved in some reviews on, you know, base layer chains. 6 00:00:30,000 --> 00:00:36,380 Like Eth2, Prism Implementation, and AvaLabs as well. 7 00:00:36,420 --> 00:00:40,800 And the girl beside me, that's my daughter, just by the way. 8 00:00:40,800 --> 00:00:42,240 And next one. 9 00:00:42,480 --> 00: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. 10 00:00:53,380 --> 00:00:59,080 But basically, what I wanted to share today is kind of the status quo on testing. 11 00:00:59,080 --> 00:01:04,020 From an auditor's point of view, and mainly focusing on composability. 12 00:01:04,600 --> 00:01:11,560 As projects integrate with others more closely, how are people right now testing their projects? 13 00:01:11,560 --> 00:01:14,580 And what I believe would be beneficial. 14 00:01:15,160 --> 00:01:22,180 I will also introduce my personal project on trying to improve testing with two simple examples here. 15 00:01:22,960 --> 00:01:24,920 So, next one. 16 00:01:25,720 --> 00:01:30,520 So, the main challenge here is the composability. 17 00:01:30,520 --> 00:01:32,420 So, what is composability? 18 00:01:32,560 --> 00: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. 19 00:01:41,620 --> 00:01:44,280 That's from MakerDAO. 20 00:01:44,280 --> 00:01:51,380 And although blockchain projects have always been composable, you know, like it's always open API, right? 21 00:01:51,380 --> 00: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. 22 00:02:04,300 --> 00:02:13,220 In the beginning, we see most of projects focusing just building on their own ecosystem, pretty much independent from other projects. 23 00:02:13,220 --> 00:02:18,500 They issue these tokens just hoping other to use, maybe to trade. 24 00:02:18,500 --> 00: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? 25 00:02:31,340 --> 00:02:32,740 Kind of like Lego. 26 00:02:32,740 --> 00:02:35,500 So, that's the term money Lego. 27 00:02:35,920 --> 00:02:41,920 And easily connecting them together to create like so many different kinds of functionalities. 28 00:02:41,920 --> 00:02:48,480 Of course, exchanges are the first one, you know, just aggregates just using the interface and then sell them. 29 00:02:48,500 --> 00:02:53,940 They're just using the token, not really the internal functionality, right? 30 00:02:54,380 --> 00: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. 31 00:03:04,880 --> 00:03:12,240 Oracle feeds us like maybe real world data and then allows us to use them on chain. 32 00:03:12,240 --> 00:03:17,660 So, it is also like an important piece in this composability, I would say. 33 00:03:18,220 --> 00:03:19,860 So, next one. 34 00:03:21,800 --> 00:03:25,580 So, composability is certainly a blessing. 35 00:03:25,580 --> 00:03:32,860 So, we see that there are so many interesting projects in the past few years that emerges from here, right? 36 00:03:32,860 --> 00:03:40,400 Pulled together as one example, it builds like no loss lottery on top of the compound protocol, right? 37 00:03:40,520 --> 00:03:45,200 So, as time goes by, like projects tend to grow more complex. 38 00:03:45,200 --> 00:03:50,280 One of the prime example recently would be the Yearn protocol, right? 39 00:03:50,280 --> 00:04:00,980 That helps user yield farming by putting together like Curve, AVI, Compound, MStable, and a lot of other protocols, right? 40 00:04:00,980 --> 00: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. 41 00:04:11,120 --> 00:04:12,800 Now, next. 42 00:04:13,600 --> 00:04:18,860 However, this composability is also a curse, right? 43 00:04:18,860 --> 00:04:26,660 So, we have already witnessed several attacks and one systematic failure that affected the whole DeFi community. 44 00:04:26,660 --> 00: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? 45 00:04:38,740 --> 00: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. 46 00:04:53,740 --> 00: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. 47 00:05:05,480 --> 00:05:11,580 And then the hacker was able to just dump the WBTC and profit from there. 48 00:05:11,580 --> 00:05:19,120 So, you see like this complexity is also opens a lot of like, you know, different kinds of attack. 49 00:05:19,440 --> 00:05:20,980 That's for one. 50 00:05:20,980 --> 00:05:22,660 And next. 51 00:05:24,760 --> 00:05:28,980 And we also see like in the black Thursday, right? 52 00:05:29,260 --> 00:05:35,320 Not sure if the graph is visible, but we probably all know, they grew up for 30%. 53 00:05:36,740 --> 00:05:44,520 At the same time, so MakerDAO price did not update for a while. 54 00:05:44,520 --> 00:05:46,420 So they do have like Oracle. 55 00:05:46,420 --> 00:05:51,820 But during that time, the gas price was extremely high. 56 00:05:51,880 --> 00:05:57,920 And thus the price was not able to update in real time. 57 00:05:57,920 --> 00:06:02,620 And when it updated, it triggered like a massive liquidation. 58 00:06:03,210 --> 00:06:10,420 In turn, this is one of the reasons why like, there are so many collateral were auctioned off for zero. 59 00:06:10,980 --> 00:06:17,440 So, part of this is because of the Oracle issue here. 60 00:06:18,140 --> 00:06:19,320 So, next. 61 00:06:21,160 --> 00:06:27,040 So, I would say composability is almost like a nightmare for developers. 62 00:06:27,040 --> 00:06:37,900 Repeatedly see this issue, like causes a lot of troubles for developers, especially when it comes to testing the project, right? 63 00:06:37,900 --> 00:06:44,260 Like, how should the developer ensure the project that they interface with are working as expected? 64 00:06:44,580 --> 00:06:48,880 And then how, like, this is already hard, right? 65 00:06:48,880 --> 00:06:57,300 And so, I don't really see anyone like testing extreme scenarios, like the ones that we would mention above. 66 00:06:58,220 --> 00:07:00,660 So, let's go on to the next. 67 00:07:02,280 --> 00:07:06,980 So, the status quo on testing, kind of doing a review. 68 00:07:07,600 --> 00: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. 69 00:07:18,780 --> 00:07:28,180 But when it comes to testing the integration points with other projects, what we see, you know, some variety there. 70 00:07:28,300 --> 00: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. 71 00:07:37,920 --> 00:07:40,300 This is possible when it's small, right? 72 00:07:40,300 --> 00:07:46,020 But it's impossible if the external project is complicated. 73 00:07:46,020 --> 00:07:50,880 Just imagine, like, you're deploying the whole MakerDAO system. 74 00:07:50,880 --> 00:07:52,860 Well, that's going to be a nightmare. 75 00:07:53,820 --> 00:07:54,740 Next. 76 00:07:55,280 --> 00:08:02,140 And so, there's the second option, which is mocking the external protocol, right? 77 00:08:02,140 --> 00:08:08,160 A developer has to understand what the external contract would do and mock the behavior accordingly. 78 00:08:09,200 --> 00:08:20,940 Oftentimes, developers will simplify these logic to, you know, to not really implement everything in the protocol, but just the behavior. 79 00:08:20,940 --> 00:08:27,300 And so, there are possible discrepancies between the mocked contract and the real behavior. 80 00:08:27,300 --> 00:08:30,800 And that actually presents a potential risk. 81 00:08:31,340 --> 00:08:36,640 Now, next on, we have testing on testnet, right? 82 00:08:36,640 --> 00:08:41,120 If you're interfacing with just one project, it kind of works. 83 00:08:41,120 --> 00:08:45,980 Although, it's still tedious to get all the test tokens, testnet tokens, and, like, Ether. 84 00:08:45,980 --> 00:08:47,900 You need the faucet for that. 85 00:08:48,020 --> 00: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. 86 00:09:00,440 --> 00:09:03,620 Like, MakerDAO, they probably have their own testnet. 87 00:09:03,620 --> 00:09:09,900 But for sure, I know Aave and Compound, they use, like, different dymocks on the testnet. 88 00:09:09,900 --> 00: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. 89 00:09:27,140 --> 00:09:29,000 Now, next. 90 00:09:29,960 --> 00:09:35,060 Ah, well, here we have testing on mainnet. 91 00:09:35,060 --> 00:09:38,060 And needless to say, this is super costly. 92 00:09:38,420 --> 00:09:45,100 Typically, it only allows functional and high-level manual testing, you know. 93 00:09:45,100 --> 00:09:52,140 And so, among all these, I would say the most common ones are mocking. 94 00:09:52,940 --> 00:09:58,120 But testing on testnet do exist, but typically done, like, not very extensively. 95 00:09:59,000 --> 00:10:08,700 Because developers, like, oftentimes find, you know, fetching those resources very, very troublesome, right? 96 00:10:08,700 --> 00:10:15,480 And so, I have personally seen projects that did both the mock and testing on testnet. 97 00:10:15,480 --> 00: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. 98 00:10:22,320 --> 00:10:30,300 Because that requires some understanding of the underlying protocol and how they would behave. 99 00:10:30,300 --> 00:10:32,280 So they missed that in the mock. 100 00:10:32,860 --> 00: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. 101 00:10:44,380 --> 00:10:47,300 So, like, they missed the profit sharing part. 102 00:10:47,400 --> 00:10:50,420 And we were able to locate that issue, luckily. 103 00:10:51,080 --> 00: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. 104 00:11:07,940 --> 00:11:08,920 Next. 105 00:11:11,120 --> 00:11:19,260 And so, with the standard tool, actually, I do, there are one option that I would say it's quite nice. 106 00:11:20,420 --> 00:11:24,340 I do recommend, like, testing under this mainnet fork. 107 00:11:24,340 --> 00:11:35,240 And Ganache provides this fork option, which, surprisingly, I haven't seen any project uses this to test external library. 108 00:11:35,700 --> 00:11:41,120 And that's probably because of my side note right there. 109 00:11:41,420 --> 00:11:44,720 The fork does have some bug. 110 00:11:45,280 --> 00: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. 111 00:11:59,040 --> 00:12:03,140 So, but there is a pull request, but I don't think a lot of people know that. 112 00:12:03,140 --> 00:12:06,740 I think that's probably one of the reasons that this is not used. 113 00:12:06,740 --> 00:12:13,920 But if this is used and fixed, then I see this is actually pretty nice. 114 00:12:14,520 --> 00:12:20,360 Projects interconnect with each other the same way as mainnet, because it's the mainnet fork. 115 00:12:20,360 --> 00:12:24,020 There's, of course, no cost, because it's a local Ganache. 116 00:12:24,140 --> 00:12:29,820 And then huge amount of ethers when starting up the local blockchain, as always. 117 00:12:30,500 --> 00:12:35,160 And, you know, Ganache also allows you to sign transaction as other accounts. 118 00:12:35,160 --> 00:12:39,120 So you can be the whale, you know, anytime. 119 00:12:39,120 --> 00:12:41,120 So this is already pretty nice. 120 00:12:41,830 --> 00:12:42,610 Next. 121 00:12:43,480 --> 00:12:52,220 So with this, we can already start to model a systemic threat, which is the whale, right? 122 00:12:52,220 --> 00:12:59,620 For example, to be a die whale here, well, you can use an unlock account. 123 00:13:00,060 --> 00: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. 124 00:13:13,600 --> 00:13:14,800 So that's good. 125 00:13:14,800 --> 00: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. 126 00:13:23,780 --> 00:13:26,280 You need to find another die whale. 127 00:13:26,660 --> 00:13:32,180 So, you know, not really reliable as test, I would say. 128 00:13:33,500 --> 00:13:39,380 The other two paths that you can do is that you can, of course, mint die on MakerDAO. 129 00:13:39,380 --> 00: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? 130 00:13:46,360 --> 00:13:54,020 But you have to know how to open vault, lock up collateral and use that to mint die. 131 00:13:54,040 --> 00:13:59,120 But in the end, what you really want is just increasing your balance in the die. 132 00:13:59,120 --> 00:14:02,700 You know, it's pretty tedious and going through all that. 133 00:14:02,700 --> 00:14:04,860 And same for buying die on DEX. 134 00:14:04,860 --> 00:14:11,240 If you want to do that, you need to know Uniswap's interface, perhaps, and how to interact with them. 135 00:14:11,520 --> 00:14:16,360 So it's not as convenient. 136 00:14:17,000 --> 00:14:18,160 So, next. 137 00:14:20,720 --> 00:14:24,800 Yeah, and still, like, some risk remains very hard to model. 138 00:14:25,470 --> 00:14:33,780 Like, if modeling a risk involves changing the price feed on MakerDAO or Uniswap v2, that may be a problem. 139 00:14:33,940 --> 00: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. 140 00:14:53,520 --> 00:15:01,120 What would happen if there is a mismatch on my protocol, right? 141 00:15:01,120 --> 00:15:02,620 Can I model that? 142 00:15:03,180 --> 00:15:07,760 And then, you know, seeing the BZX attack, that's pretty sophisticated. 143 00:15:08,180 --> 00:15:12,600 It might be very hard to come up with that sort of scenarios. 144 00:15:12,600 --> 00: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? 145 00:15:24,040 --> 00:15:25,420 That's much easier. 146 00:15:25,420 --> 00:15:33,060 But in this mainnet fork, you cannot do that because you still have to follow all the blockchain rules, right? 147 00:15:33,060 --> 00: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. 148 00:15:43,480 --> 00:15:53,860 So, the question, next one, is what if we could ignore code as law, you know, on the local blockchain? 149 00:15:53,860 --> 00:16:00,380 And what if, like, can we change the storage directly without any permission? 150 00:16:00,820 --> 00:16:02,180 Next one. 151 00:16:03,500 --> 00: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. 152 00:16:17,680 --> 00:16:23,820 And so, ganache itself, it kind of looks like this, you know, like the related part. 153 00:16:23,820 --> 00:16:30,540 It has WS server, HTTP server, and it connects to this get API module that it has internally. 154 00:16:30,540 --> 00:16:40,980 This get API module controls the state manager, and it's supported by a VM, which is the Ethereum JS VM. 155 00:16:41,600 --> 00:16:44,980 So, next. 156 00:16:47,120 --> 00: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. 157 00:17:05,440 --> 00:17:15,040 By using these, essentially, you can directly modify the storage and the state of the local ganache. 158 00:17:15,140 --> 00:17:23,820 So, what typically was done is that you still go through ganache and send transaction to ganache. 159 00:17:23,820 --> 00: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. 160 00:17:34,620 --> 00:17:38,620 I just directly want to modify my storage right there. 161 00:17:38,880 --> 00:17:44,100 So, that's the root of my project. 162 00:17:44,100 --> 00:17:46,160 And so, next one. 163 00:17:47,640 --> 00:17:53,240 So, after some development, like, this is my project, which I call Godmode for Test. 164 00:17:53,240 --> 00:17:55,920 It basically consists of three parts. 165 00:17:56,220 --> 00:18:00,920 The project itself is still in, like, very early stage and still needs a lot of work. 166 00:18:00,920 --> 00:18:10,560 It already works, and I personally use it for development, especially when it's come to DeFi projects. 167 00:18:10,560 --> 00:18:14,500 So, what I built consists of three pieces. 168 00:18:14,500 --> 00:18:18,520 The first one is this ganache core. 169 00:18:18,520 --> 00:18:27,900 So, this modified ganache core allows us to ignore the blockchain log and just directly modify the storage, as previously stated. 170 00:18:27,900 --> 00:18:37,100 And then, on top of that, I created a wrapper JavaScript library that you can integrate into the Truffle framework. 171 00:18:37,120 --> 00:18:46,900 So, you know, all the familiar tools that we use and leverage the Solidity contract as sort of an API. 172 00:18:46,900 --> 00:18:52,260 I think it's easier to understand how to modify the storage of the blockchain. 173 00:18:52,820 --> 00:18:55,680 And there's some set of precompiled contracts. 174 00:18:56,560 --> 00:19:00,800 So, what the precompiled contracts would do... 175 00:19:01,260 --> 00:19:01,920 next, please... 176 00:19:03,500 --> 00:19:10,740 is, you know, I want to provide some easy-to-set-up scenarios for the developers. 177 00:19:10,740 --> 00: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. 178 00:19:28,580 --> 00: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. 179 00:19:40,740 --> 00:19:41,900 Next. 180 00:19:44,060 --> 00:19:46,820 And in a more general sense... 181 00:19:47,580 --> 00:19:54,020 So, this is a general API that I provide that you can basically craft... 182 00:19:55,960 --> 00:20:00,720 use this to modify, like, arbitrary contract storage. 183 00:20:00,720 --> 00:20:06,920 And so, it might not be very clear just by seeing this. 184 00:20:06,920 --> 00:20:10,100 And so, I'll demonstrate a few examples. 185 00:20:10,960 --> 00:20:15,660 I'm happy that I have had the backup of, like, kind of all the screenshots. 186 00:20:16,380 --> 00:20:18,320 And so, yeah, we'll... 187 00:20:18,320 --> 00:20:19,540 I kind of... 188 00:20:19,540 --> 00:20:24,100 I will kind of walk you through, like, all the screenshots on doing these things. 189 00:20:24,660 --> 00:20:25,960 So, yeah. 190 00:20:25,960 --> 00:20:27,980 So, next one. 191 00:20:28,140 --> 00: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. 192 00:20:42,780 --> 00:20:45,640 But right now, I just wanted to show you how this could be done. 193 00:20:45,660 --> 00:20:53,360 And so, the first step would be you go and find Dai's source code and mainnet address. 194 00:20:53,360 --> 00:20:56,620 And, of course, both are available on Etherscan. 195 00:20:56,620 --> 00:20:59,320 So, you go there, copy it down. 196 00:20:59,320 --> 00:21:05,100 I'm assuming that we're using, like, Truffle project framework here. 197 00:21:05,100 --> 00:21:10,140 So, we just store the Dai source code under the contracts folder. 198 00:21:10,780 --> 00:21:11,900 Next one. 199 00:21:15,000 --> 00:21:22,360 And so, the following step is we clone that Dai contract, you know, rename it. 200 00:21:22,360 --> 00:21:26,960 So, now we would have, like, let's say two contracts. 201 00:21:26,960 --> 00:21:27,940 One is Dai. 202 00:21:27,940 --> 00:21:31,260 Let's say the other one is called gmDai. 203 00:21:32,500 --> 00:21:36,080 And we modify the mint function. 204 00:21:36,080 --> 00:21:39,140 So, how we modify it, it's really simple. 205 00:21:39,140 --> 00:21:45,980 The reason that we cannot mint Dai is it was authorized. 206 00:21:45,980 --> 00:21:47,880 Like , it is controlled. 207 00:21:48,600 --> 00:21:55,420 There's a requirement statement that prevents us from going in, which is this modifier auth, right? 208 00:21:55,420 --> 00:21:59,540 So, what we can do is just to remove that auth. 209 00:21:59,540 --> 00:22:05,380 And that allows anyone to call this mint. 210 00:22:05,380 --> 00:22:10,040 So, you know, that's essentially how it's done. 211 00:22:10,180 --> 00:22:10,940 Next. 212 00:22:14,080 --> 00:22:20,460 And so, in the normal test, and this is how we would write it. 213 00:22:20,740 --> 00:22:30,540 So, we have, we would require both artifacts, include both artifacts into the test, which is the Dai and gmDai. 214 00:22:30,540 --> 00:22:37,500 So, you recognize gmDai is the one that we just modified and removed the modifier, right? 215 00:22:38,160 --> 00: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. 216 00:22:51,600 --> 00: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. 217 00:23:01,740 --> 00:23:07,580 So, what you do here is actually you're executing the Dai contract. 218 00:23:07,580 --> 00:23:11,960 So, you see this Dai contract is just like two lines above. 219 00:23:11,960 --> 00:23:15,860 It's, it was like a way to Dai at this address. 220 00:23:15,860 --> 00:23:20,880 And that's the address of the main net Dai address, right? 221 00:23:20,880 --> 00:23:31,440 And so, I execute this Dai contract as if it is the modified contract. 222 00:23:31,740 --> 00:23:38,800 So, I'm actually just executing, you can think of it that this way. 223 00:23:38,800 --> 00:23:43,560 So, I am modifying the storage of Dai contract. 224 00:23:43,560 --> 00:23:51,840 But according to the rules set by this gmDai artifact or contract. 225 00:23:51,840 --> 00:23:58,760 And so, here, essentially, I'm just calling mint from the gmDai contract. 226 00:23:58,760 --> 00:24:02,600 Then I say, give Alice this amount of Dai. 227 00:24:02,740 --> 00:24:05,140 And the next line is assertion. 228 00:24:05,280 --> 00:24:10,160 And so, this is, yeah, this is basically how it works. 229 00:24:11,420 --> 00:24:12,760 Next one. 230 00:24:15,360 --> 00:24:19,400 Now, so, that's the, that's just minting Dai. 231 00:24:19,400 --> 00:24:25,060 And so, as a second example, I'll show you how to modify to make a DAO price feed. 232 00:24:25,060 --> 00:24:36,260 Now, this is an essential step for modeling this systemic threat, like, you know, oracle attacks and all of that. 233 00:24:36,260 --> 00:24:47,460 Because what you want to do is to have, like, maybe two oracles report different values, right? 234 00:24:47,460 --> 00:24:52,100 So, you want to read and perhaps change to make one of the oracles price feed. 235 00:24:52,100 --> 00:24:53,980 Here, I chose my DAO. 236 00:24:53,980 --> 00:24:59,360 And, of course, you just Google and find out where the maker DAO is getting their price. 237 00:25:00,300 --> 00:25:05,160 And so, this is the address that I found on their page. 238 00:25:05,200 --> 00:25:10,540 And then you just go to that ether scan the same way we did as Dai. 239 00:25:10,540 --> 00:25:12,540 And then copy the source code. 240 00:25:13,400 --> 00:25:14,680 Next one. 241 00:25:17,590 --> 00:25:22,270 Yeah, and, you know, this is still a little bit technical. 242 00:25:22,270 --> 00:25:25,970 You have to understand kind of how it works. 243 00:25:25,970 --> 00:25:29,070 But luckily, most of the oracles are pretty simple. 244 00:25:29,070 --> 00:25:31,590 They're basically reporting what they have. 245 00:25:31,590 --> 00:25:33,310 Maybe they have something else. 246 00:25:33,310 --> 00:25:38,790 Like, in this maker DAO price feed, this OSM module is their oracle. 247 00:25:38,790 --> 00:25:42,870 I think it's oracle security module or something like that. 248 00:25:43,210 --> 00:25:46,870 So, OSM module basically has an example. 249 00:25:46,870 --> 00:25:49,770 Hey, OSM peak is getting the current value. 250 00:25:49,770 --> 00:25:52,670 Or OSM read is getting the current value or fail. 251 00:25:52,670 --> 00:25:56,330 And so, you go and look at the source code of OSM. 252 00:25:56,330 --> 00:26:04,290 And you find out that, ah, it is actually returning the value from this curr.val, right? 253 00:26:04,290 --> 00:26:08,210 So, this is where the current value is storing. 254 00:26:08,990 --> 00:26:14,590 And so, what we want to do is basically just read this one. 255 00:26:14,590 --> 00:26:20,190 And, you know, and perhaps modify it. 256 00:26:20,190 --> 00: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. 257 00:26:31,470 --> 00:26:34,330 There's a modifier called tall. 258 00:26:34,330 --> 00:26:42,510 And that prevents any user, like, external contracts from using, from reading the value here. 259 00:26:42,510 --> 00:26:49,450 But if we want to just use, just inspect this value, we can actually do that. 260 00:26:50,290 --> 00:26:51,170 But, okay. 261 00:26:51,170 --> 00:26:52,450 So, next one. 262 00:26:56,560 --> 00:27:02,660 And so, yeah, kind of same way we did on the die to GM die. 263 00:27:02,660 --> 00:27:12,520 So, we modify the clone OSM module, add these two functions and event. 264 00:27:12,520 --> 00:27:21,100 The reason I do event is that, unfortunately, right now, it doesn't read. 265 00:27:21,440 --> 00:27:28,880 So , this execute as cannot just read a function. 266 00:27:28,880 --> 00:27:31,500 You know, like, it will always do a state change. 267 00:27:31,500 --> 00:27:35,960 So, if you do a view function, then it will revert on that. 268 00:27:35,960 --> 00:27:37,960 So, this is kind of a workaround. 269 00:27:37,960 --> 00:27:41,740 But nevertheless, you can still get the value this way. 270 00:27:41,740 --> 00:27:47,440 And then, the next one is pretty simple, which is just setting that current value. 271 00:27:47,440 --> 00:27:47,540 Right ? 272 00:27:47,540 --> 00:27:52,300 So, set curve val and curve dot val equals to the new value that we have. 273 00:27:52,860 --> 00:27:54,060 Next one. 274 00:27:56,620 --> 00:28:03,760 And so, with this, you know, we can just write test to check the behavior. 275 00:28:04,700 --> 00: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. 276 00:28:19,980 --> 00:28:26,580 And then, the next two lines, this transaction, weird transaction thing is reading from the logs. 277 00:28:26,580 --> 00:28:28,560 Basically, reading from the events. 278 00:28:28,560 --> 00:28:33,640 And then, reading the current value out of that event. 279 00:28:35,160 --> 00:28:39,960 So, in the middle, there's this await got node execute. 280 00:28:39,960 --> 00:28:41,980 So, here, again, it's the same thing. 281 00:28:41,980 --> 00:28:48,300 We're executing this OSM contract as our modified contract. 282 00:28:48,300 --> 00:28:54,160 And now, you see that this set curve val is a function that we added. 283 00:28:54,160 --> 00:28:57,820 It's not anywhere in the original contract. 284 00:28:57,820 --> 00:29:00,000 And we just added that part. 285 00:29:00,000 --> 00:29:06,160 But now, this modified ganache will be able to run this thing. 286 00:29:06,320 --> 00:29:13,080 And then, it will just set the curve that val into this new function. 287 00:29:13,080 --> 00:29:14,100 Oh, sorry, value. 288 00:29:14,660 --> 00:29:19,980 And I just printed out, print the value again to see what's there. 289 00:29:21,560 --> 00:29:23,000 Next one. 290 00:29:24,420 --> 00:29:27,860 So, now, yeah, this is kind of the result. 291 00:29:27,860 --> 00:29:38,080 You'll see that the original value is this, basically, 387 USD, right? 292 00:29:38,080 --> 00:29:43,880 And then, I just set it to some number that I just thought set there. 293 00:29:44,120 --> 00:29:49,340 So, now, you are able to change the make and dial price feed with this thing. 294 00:29:51,980 --> 00:29:54,140 Yeah, so, next one. 295 00:29:55,620 --> 00:30:03,440 So, some downside of this tool is that mainnet fork can be buggy for the ganache. 296 00:30:03,900 --> 00:30:08,800 So, the fix that I have there in the side node is not official. 297 00:30:09,740 --> 00:30:13,120 So, you know, sometimes, there are some bugs there. 298 00:30:13,220 --> 00:30:21,460 And the second one, you kind of already saw that we cannot create view function and return properly yet. 299 00:30:21,460 --> 00:30:22,900 So, I'm still working on that. 300 00:30:24,880 --> 00:30:28,300 And, of course, this is a local ganache. 301 00:30:28,300 --> 00:30:32,320 So, you cannot simulate how others would behave. 302 00:30:32,320 --> 00: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? 303 00:30:45,620 --> 00:30:48,380 So, you're alone in this local blockchain. 304 00:30:48,380 --> 00:30:51,600 That's kind of an inherent limitation here. 305 00:30:52,540 --> 00:30:59,440 And fourth is this arbitrary modify storage is sometimes too powerful. 306 00:30:59,440 --> 00:31:05,400 Because, you know, it can get you to state that are just not possible to reach. 307 00:31:06,140 --> 00:31:13,480 So , you have to be careful about and thinking about what kind of scenarios you want to craft. 308 00:31:13,480 --> 00:31:15,420 And if that is a reasonable scenario. 309 00:31:15,420 --> 00:31:24,960 Because before this tool, you have to think of ways to get to a state. 310 00:31:24,960 --> 00:31:26,910 And then you can start testing. 311 00:31:27,420 --> 00:31:31,420 Now, with this tool, you can get to any state directly. 312 00:31:31,420 --> 00:31:36,070 But whether that state makes sense or not, that's another question. 313 00:31:36,460 --> 00:31:41,560 So, that's another problem that we have to take care and think about. 314 00:31:41,820 --> 00:31:42,670 Yeah. 315 00:31:43,420 --> 00:31:45,400 And so, next one. 316 00:31:47,400 --> 00:31:56,980 Kind of a conclusion is that DeFi composability is currently both a blessing and a curse. 317 00:31:57,100 --> 00:32:04,980 I hope that with more testing facilities, we can turn it into a pure bliss. 318 00:32:05,680 --> 00: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. 319 00:32:14,880 --> 00:32:20,200 Let alone testing extreme scenarios to prevent systemic threats. 320 00:32:21,320 --> 00: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. 321 00:32:33,260 --> 00:32:33,780 Right? 322 00:32:33,780 --> 00:32:37,720 But this is mainly because there's no... 323 00:32:38,520 --> 00:32:42,240 Well, there are not a lot of tools that support this. 324 00:32:42,300 --> 00:32:43,260 Right? 325 00:32:43,260 --> 00:32:47,840 And so, I believe there's still a lot of space to improve in testing. 326 00:32:47,840 --> 00:32:51,260 Especially in terms of this composability thing. 327 00:32:51,900 --> 00:32:54,620 And I think we need... 328 00:32:55,500 --> 00:32:57,960 This presentation is almost like... 329 00:32:58,840 --> 00:33:04,080 I would treat it like an open invitation for everyone to kind of work on this area. 330 00:33:04,420 --> 00: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. 331 00:33:19,320 --> 00:33:20,060 Yeah. 332 00:33:20,060 --> 00:33:21,320 And that's it. 333 00:33:21,320 --> 00:33:23,480 Thank you for your time. 334 00:33:23,480 --> 00:33:24,640 Great presentation. 335 00:33:31,830 --> 00:33:32,990 All right. 336 00:33:32,990 --> 00:33:34,910 Any questions? 337 00:33:38,410 --> 00:33:40,110 Ah, I see. 338 00:33:40,110 --> 00:33:47,150 Are there limitations between forking mainnet from full versus archive nodes? 339 00:33:47,150 --> 00:33:51,530 Ah, it depends. 340 00:33:51,530 --> 00:33:59,350 So , I actually just used Infura, not even the full node. 341 00:33:59,350 --> 00:34:02,130 Oh, Infura is the full node, right? 342 00:34:02,130 --> 00:34:04,550 Yeah, but I've just been using Infura. 343 00:34:04,550 --> 00:34:12,670 And if you just care about how it's going to react at its current stage, I think that's fine. 344 00:34:13,390 --> 00: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. 345 00:34:23,790 --> 00:34:26,180 Then that would start failing. 346 00:34:27,390 --> 00: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. 347 00:34:42,080 --> 00:34:42,810 Yeah, 348 00:34:48,880 --> 00:34:51,040 no problem. 349 00:34:51,040 --> 00:34:52,220 My pleasure. 350 00:34:54,200 --> 00:35:03,460 Ah, yes, let me paste my GitHub repository into the chat. 351 00:35:03,860 --> 00:35:11,520 I have to warn everyone that this is like a very, very, you know, initial work. 352 00:35:11,520 --> 00:35:14,060 It works, but it's very ugly. 353 00:35:14,860 --> 00: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. 354 00:35:24,240 --> 00:35:26,160 So I'm happy to share. 355 00:35:35,400 --> 00:35:38,760 All right, any other questions? 356 00:35:38,780 --> 00:35:40,360 Thank you, Miko. 357 00:35:53,150 --> 00:35:54,650 Thank you. 358 00:35:54,650 --> 00:35:56,230 Thank you. 359 00:35:56,230 --> 00:35:59,450 Do we have other questions, like in Twitch?