Detecting pitfalls in ERC4337 implementation | Martinet, QuantStamp | ETHTaipei 2024
ETHTaipei·Wed, Oct 9, 2024, 12:00 AM
Detecting pitfalls in ERC4337 implementation | Martinet, QuantStamp | ETHTaipei 2024
Transcript
thank you Anton for the introduction and I absolutely love Tim when he was mentioning about account abstraction and how actually it longterm helps like the security because you involve like other uh parties here and this actually is a good segue because that's the long-term plan however the shortterm thing is that you need someone um you know to to be able to properly imp implemented and implementing it correctly actually isn't that easy easy ERC uh this ERC 4337 account exraction uh well here's the subtitle oh damn it's not that easy uh so this is the talk um the main author of the uh talk and then the toour is poan Ling he's also a Taiwanese uh right now based in Japan and I am presenting because I kind of like guided uh with him and work with him on this project so uh quick intro about account exraction so um you know there are a lot of benefits I'm just like really simplifying it here right here uh first of all it's allows us to have different kind of signature schemes so not really just limited to the ecdsa that we have right now we have other ways to authenticate we may have like ZK proof we may have like Crossing uh authentication all these kind of stuff right so that is awesome because that opens up different kind of signature schemes um and other than that we we are able to have like wallet recovery well um you know like right now even for myself to keep the private key in a safe place it's kind of hard it's kind of annoying and having the recovery thing is very user friendly like hey I forgot my password like I do that a lot probably daily um and you know it will be nice for for uh wallet to have that as well and account distraction does provide that session Keys as well and also gas user experience for example um I am paying not it doesn't require for me to have ether to pay right now that is mostly the case but later with account exraction I should be able to pay the gas with usdc with whatever token actually is in my wallet right so U these are all the great things uh that comes with account abstraction um and the there's a lot of different ways about abstraction so uh that's just a huge concept it has been discussed widely and how to implement it uh one of the ways that was discussed was impr protocol like you have to change the consensus mechanism you have to change ethereum itself and that was sort of like a put away because that was too much work and this is kind of like the latest one that seems to start gain adoption and the reason for it the first thing is actually well no ethereum consensus level change which is awesome because you know like for having a consensus level change is very very uh serious thing a big thing right no new OP codes it's good and this is purely on the smart contract application Level now what that this kind of like enables or like um you know uh opens up is like okay now we have a user operation not transaction another kind of mol um you might say um that exists so it creates another layer not transaction just some sort of like intent like um operations and then you have another uh party which is the bandler who who takes in the user operation and then actually compiles it into transaction uh and then send it onchain so um high level this is the case uh onchain how it does uh how or how it works is that on ethereum or on every chain there should be like one single entry point that that is uh deployed by a third party and so you only need one such smart contract in each chain and other people will like as a user I will send my user operation to a bundler bundler picks it up creates transaction send it to the entry point that's essentially the flow that is essentially the flow all right and here we go this is the flow that we're talking about we have users that send their user operation so I'm going to remind you about how it looks like before before it's user directly sends the transaction to the blockchain here let's assume this part is blockchain right it s directly to the blockchain that spend gas you know like all those kind of stuff now it creates another layer it creates a bundler right here and then on the on the ethereum or on the blockchain it has this entry point uh smart contract that is universal that interacts with all your accounts Etc now uh the user sends the user operations to the bundler the bundler calls a unique like a specific function which is called handle Ops and the entry point does a couple things first it validates the operation whether this is okay uh to execute um and after it validates like okay this everything is safe-ish then it executes uh now we'll need to dive a little bit more here about why do we need this validation uh thing um well the first thing is you want to prevent like the do uh issue so um here let's go to the next one the first thing the bundler wants to do is to check uh on the simulation uh during the simulation like hey uh can I execute this or not will this transaction revert because imagine the bundler is the one that actually sends the transaction for you so they spend the gas so there's one huge attack vector and basically all the complexity of ERC uh this account abstraction EIP is is around this core idea that I don't want to be dos and how do you get dos uh you basically as a bandler if when you simulate it looks good and then when you send a transaction it reverts well then you're just wasting your gas right and so that is the way how the bundler can get attacked this is the core idea and everything all the these like complex mechanisms are basically just surrounding that just surrounding that um we will not go into all the details of how like all those like limitations however we can like kind of like quickly get a glance right so you know it's just a snippet from the EIP standard itself you see there is forbidden upcodes uh there is Storage restrictions and there there's reasons for that first of all forbidden up codes gas priz gas limit difficulty time stamp Bas block has all these things why because they change they may change all the time right during your simulation it's one thing right the gas price is one thing uh when you actually execute it's another value so it this these a lot of these are basically just non-consistent um op codes they they will return non-consistent values and that's why they're forbidden because going back to the previous slide you want to simulate and if this one passes then uh you send the transaction and if there's inconsistencies then there's a risk for you to get doed that's why these are forbidden so you know simple as that um storage uh there are two things one is it's only able to access say its own storage so of course like as a contract you can read other uh contract storage Etc right but you can also read yourself storage uh so there is no restriction on reading your own storage so that is that part is good that part is okay uh however there is a there is a restriction on external source and this part so these this part is actually slightly confusing slightly confusing uh the reason that it is required to kind of like uh well limited to only able to access associate storage uh perhaps we can think of just another like counter example which is I have a contract then I and I'm just like reading another storage that is shared and some other contracts will also write it the problem with that also going back to this thing is that uh during the simulation the state of that external contract can be one thing right and when you actually send the transaction just imagine literally you got front run someone else changed that storage and that will essentially revert uh your transaction and so it goes back to the same principle you don't want to get revert you don't want to get do um so that's the reason but why do we allow Associated Storage and what is Associated Storage associate storage basically means that storage that will well as the name suggests Associated to me right uh so for example if I am a wallet I want to be able to access like hey my balance uh my erc20 balance in some random tokens right and how do you do that you call balance address right and then you you get your own like balance that's how you um obtain you know your own balance and balance address is exactly this uh in the op code or in the deeper level it is exactly saying that hey I want to uh calculate this number and access that storage that is related to me that's why they Define these uh seemly seemingly complicated things like oh kch 256 and then a or xn plus n like basically it wants to still enable or allow the use cases that I am uh you know like erc20 tokens balance address and this address is my wallet's address right so it wants to be able to like hey this is a common use case let's allow that so that's being defined as Associated Storage all right now that is sort of easy to understand easy to understand because you know you have the basic principle and then that's uh after hopefully after my uh explanation like the principle itself is easier understand however it's hard to remember like hey look at all this thing how would you remember this thing and then when you are writing the smart contract you're not even looking at these things these are in the up code level right it's you're not really looking at these stuff like so it is actually hard to detect um and not only that actually we're going to talk about it in a sec so of course when you're writing it's easy to forget like hey these limitations exist so obviously you're going to write uh it's possible that you write something that will violate uh the EIP uh and of course that's a problem uh the problem is not as severe as other vulnerabilities other vulnerabilities basic uh it could be like oh my I you will get wrecked like my funds get lost and like someone will steal my stuff and these type of things is essentially kind of like dos like going back to this one the effect of you writing a smart contract that violates the EIP itself is when your user sends a user operation that user operation just violates the rule and the bundler if they are security aware they should drop it so essentially your users user operation will go nowhere and your user will complain like what the heck where is my transaction I sent you promise me a better user experience and I have well I mean uh no transaction on chain I guess partly may be a good experience I don't know uh well I think it's strictly worse you you're not getting anywhere so uh that is uh the issue not as severe but it's it's like this whole thing is for improving your user experience but you're not now getting do so not good uh the common pitfalls that we saw other than just like you literally forget that you shouldn't Implement that the thing is uh there's a lot of patterns that we have adopted when we're like writing smart contracts uh like as one of the example is Beacon upgrade right you have a proxy that has that points to a beacon and this Beacon points to an actual implementation it's easy super easy to upgrade this way like you don't need to call each individual proxy like hey upgrade hey upgrade hey upgrade you don't need to do that anymore now you just need to go to the beacon and say like hey please upgrade the whole thing the whole implementation and you're good that is a very you know like life hack for smart contract desk but it this doesn't work in um in this EIP and the reason for that is simple because you are the proxy right this is the main contract address and the users uh well this is the address that you're talking to this proxy if you're following the beacon uh Beacon pattern then it goes to the beacon and the beacon reads it from somewhere and this is not associate storage because it doesn't store for your proxy like what is your proxy's implementation what's your the other proxy's implementation it's not specific to every proxy it's actually shared by everyone right everyone is actually reading the same storage slot that's the whole design of Beacon but that is exactly the design that is against the standard of EIP so wreck uh this Beacon upgrade uh pattern in account abstraction wrecked it's easy to to uh now if you look back it seems easy but actually it's very hard to detect because when you write you actually write the implementation you write the implementation you don't really think of what kind of proxy that you are going to use that's the that's the annoying part that's the annoying part so when you as a Dev you look at your EIP standard and you're like ah you know I have uh avoided all the pitfalls uh for smart contracts of writing this stand standard and then maybe another smart contract Dev or just you losing some context and like you know Beacon is a very natural thing very nice uh thing to just like integrate and you just like hook them up and it just doesn't work so the point here it's integration level the reason why it's hard it's not only there are so many limitations but also a lot of limitations or a lot of like these issues comes up during the integration this is another well another kind of like uh idea like what may go wrong right so you have a wallet contract imagine this wallet contract relies on goes to an external contract that reads maybe Oracle registry ens right it's sort of natural I want to enhance my user experience I want to query some ens and then like hey you know then you can transfer the funds directly whatever and or you have a role based account control right and this is also well I wouldn't say Comm but it's not unfamiliar or it's not unheard of you want your smart contract to have like oh you know different kinds of role Etc but if you now switch your brain not from the business side in business logic side into the smart contract development side then you'll be like oh this actually is reading a storage that is very specific like it's not Associated Storage again so again again it's integration level very hard to detect uh that's the um you know the issues of these things now we have been doing uh some work around this uh for quite quite some time uh like doing several audits Etc and then we realize that this is well of course you can rely and like hope for the best like for a human to detect all these things but it's it's these things you know it's better solved by a machine by a tool uh that's what we de and so we start this like kind of like small project to work on um and essentially we we looked at different kind of ways to do it the first one is static analysis well static analysis you take the code you analyze it B code or analyze analy it source code whatever uh then um a couple challenges I won't go into the details uh but there a couple challenges actually arise the first thing it's actually hard to know the storage slot like whether you're getting actually the associate storage right uh the second thing is related to what I was talking about the integration time like when you integrate that's exactly on runtime like um you know during runtime do you have does it invoke any forbidden op codes uh so static analysis doesn't do that because it literally just looks at this file or or the the B code of this file compile compiles into so not good not good it doesn't solve our problem there is bundler simulation which makes sense uh that's why it's yellow uh you have uh if you if you follow through the ERC 4337 then you'll see that hey they they do provide like a bundler and you can run it you can um you know just like simulate the whole transaction uh this is not easy to do this is not easy to do um you have to simulate uh there there's like so many steps like every time I want to run such a simulation I recall like spending hours like oh okay I forgot about that I need to uh I need to deploy my smart contract into this like fake gu or whatever uh this is actually very hard to do so the user experience from the developer side or auditor side is really really bad and it break it has at least like three components or four components now in my in my mind because I've done that like I basically have four small screens and one doing simulation the other doing guest the other trying to deploy smart contract and this one running the test boom I forgot to do something else that I need to do uh you know rerun the whole thing not good uh so the other thing is the ex execution dis simulation it's it's also hard because it's uh you then need to Port all of the possible or like the common actions uh that this system is doing to this simulation that you have been doing and so you're basically double doubling your work uh in that sense what we really want what we really want is that hey there is you know dev's right H well actually let me let me clarify or or correct that modify that statement a bit great devs write tests uh as Auditors know and I see Auditors smiling that not all deaths write tests unfortunately but great devs write tests right and so uh if they write tests we want a very simple way for them to be able to like or just like modify a little bit and they'll be able to detect and that's exact what we went for um won't go into the details again uh but essentially what we went for is like okay let's modify Forge uh with Forge of course well the reason why is that there Forge tests right that's what we want to work with we don't want to spin out another guess we just like want to directly simulated with Forge during the tests great uh we what we did in the nutshell is basically uh you know did some cheap ke codes or let's say extensions within Forge that's easier to understand and then uh what this allows is that we're checking all these limitations during the test during the Forge test um I think uh yeah I I I did not put that part here but essentially what we need to do is taking a developers test modify it literally two lines to invoke this uh this this cheat code and then just run it so originally the test would pass then it like with this modification if it kind of like touches these forbidden op Cod then it will just fail as simple as that so the user experience from the devs or Auditor's perspectives are great uh and so this is what we did and we're like okay great uh now see and these Mac Pro so the author is Andy um the the we were trying to find examples for this uh presentation we're like we did we did an awesome tooling uh we ran on our clients and our clients didn't have this issue for for for this and we were like well it's not fun if you cannot find any example so we just like tried to download other ERC like open- Source ones and then uh just run the tool and then we found one uh openly it's just out there um then we of course went in you know contacted them let them know uh there's some interesting things that uh right now uh you could you not should know but it's something just like interesting facts because this whole bundling bundler thing are new so bundler actually a lot of the bunders actually don't care like whether you have scent uh forbidden op code or not they literally just accept everything so this bug went undetected for for for a long time until they noticed like hey some some of the user op code were getting dropped by some of the bundles and why is that and some others are like yeah this is fine like I'll take everything um so uh it was fun so we we went and discussed you know how how disclosure it's not serious serious because it's mostly like a user experience like a do s kind of thing but from that point of view the whole point of this ERC is to create a better user experience now you have no user experience at all uh yeah not great right so we were able to find these in the wild and very very easy and that's that's how um simple it should be for for approaching these things um cool I think I'm gonna wrap up basically some conclusion uh we have worked on a lot on these like account exraction and like these what I just mentioned is basically our our experience on auditing like one of the harder part here uh integration test so you have to have tooling there's like so many limitations and then like on the integration is very hard uh this this is integration this is too many limitations like both are hard for human uh devs and Auditors alike so this is where tooling should help um unfortunately the tool is still working progress so we haven't open source it yet haven't yet but it's uh you know I think I think this it is uh worthwhile to to just tell people like hey this one there's this issue one whoever is implementing you know this account abstraction thing need to think about this at least notice that these kind of restriction exist I I think the integration part is really really tricky um because we had great uh developers that write all the tests like had like 100 coverage they still encountered this issue when they were thinking about the use cases they were like oh we can link up this account to another account and then we can do this and that and then at the time we didn't have the tooling and we were just like poking around and came across luckily came across the scenario like well actually the storage slot will not work right there that's where it kind of like all started right um this is just a reference for our past work with Alchemy so uh we have worked on 4337 and also like their Advanced version that is pushed by Alchemy the 69 nice number right I know 6900 so um yeah that's about it uh thank you for listening any questions questions yes sir yeah first of all thank you for great presentation as well I was a pleasure to read and also pleasure to read 6900 as well hope someday we have this live um so did you try to use uh Al instead of G uh the Anvil note did it work uh sorry use what the Anvil notes from Foundry annual Noe envil envil code Anvil note there is uh I think it I don't think we actually I I I'm not sure because the author is not me but I didn't get the report that we were trying on that R so yeah yeah um yeah and then maybe generally a question like what do you think uh with uh the wallets that user are going to use uh what kind of standardization you would like to see there the roll outs of the constraction or the standardization around that uh the question really is about like you know like did the bundlers really lose money on uh doing this wrong transactions Oh you mean like why didn't they drop it uh well did so did you do uh statistics about like statistics no we we did not do the statistics uh we we just noticed that like kind of in the interesting F fashion like oh you know like this one is dropping it that one is not and then like it should be dropping and so that's how we kind of like observed it but we didn't actually because I think it's very um it's basically per company their decision and um you know with bunder it's basically you have business relationship and then you send the operations to them uh you can't do statistics but that it's also kind of like I guess market cap kind of thing it's like inclining to the vulnerability management of that thing like yeah if people are losing money on that that part and I think that's part that the that is the part that we felt it was okayish because uh the violation of this one actually don't won't get you really stuck So you you're just as a user you're just not able to send the user up right so going back here just stuck here but but as a user you can still directly send your transactions over to the wallet un unless the implementation strictly forbids that which is typically not the case um so like I I feel like in this EIP when the violation happens most likely there's not as serious in the sense of uh monetary loss so that's the good thing about this whole complexity uh but the bad thing is like yeah you don't get user experience at all thank you thank you sir for your question any other questions yes sir yeah thanks Martin for the gr presentation then yeah I just wondering that since all of these things comes from the attaction of the bond dos you D so I'm just curious about that is there any other way to build the old structure for that exraction with the feature that do not uh change the foundation of the uh OB culture or anything maybe just that the ddl users will be punished at some point I don't know yeah but maybe it's can uh work around these attack with another ideas yeah I don't know yeah uh well from my kind of understanding on the whole account abstraction or this intent kind of field uh this design is more like easier on the uh protocol side so there are other ways for sure right like you change the whole protocol and then there's like huge change right there uh and from the user or from the smart contract development side that that's easy like you just you don't even need to change much right yeah uh but if you think about that practically like hey I'm going to coordinate all of these nodes to actually do the hard Fork on that then like have probably previous EO EAS to migrate over whatever that is much harder so I think I think uh in terms like spe ethereum specifically this is kind of a you know good alternative in my opinion yeah okay thank you and looking for that tooling will be over soured soon yeah yeah all right um if no other questions uh then this is great thank you everyone [Applause]
Automatic transcript — names and jargon may be misspelled.