# Ethers.js - API Hidden Gems

- Speakers: [Richard Moore](https://streameth.org/speakers/richard-moore)
- Channel: [Devcon 7 SEA](https://streameth.org/devcon_7_sea)
- Date: 2024-11-20
- Duration: 19:53
- Watch: https://streameth.org/watch/673d954917a97b4f4dd733aa

## Description

There are many shortcuts and powerful API features in Ethers.js which go unnoticed or under-exploited. The goal of this talk is to raise awareness, provide examples and encourage usage of some of these useful APIs to unlock features which can improve user experience, user security and be more transparent to users.

## About the speakers

### Richard Moore

Mostly harmless. Alphabetized. Eats breakfast. Also, the author of ethers and Firefly. The future will be awesome. He/him.


## Transcript

Hi, so I'm Richard. I work on Ethers.js. I'll try to face this one so I can talk to you, but I'll turn around. Hello all. So Ethers.js is an open source library for dealing with Ethereum. I'm guessing a lot of people here probably already use it. If not, welcome, and I hope you can try out some of these new things that I feel are like, like when I tell people these things, the common phrase is, I did not know you could do that, and then awesome. So I'll just start. And so there's different types of providers, so I'll go into a few things first. So first of all, the multi-call provider, for those that are familiar with multi-call, this is based on kind of abusing how init transactions work. So there's actually no contract on chain. It works if you're using hard hat on a pristine chain. You don't need anything deployed. It just works. I'll cover in a second how that works. But as you can, yeah, I'm going to turn around. Sorry. Anyways, you can see, so you have to pull in the Ether's extension package. You wrap your provider in a multi-call provider, and this will make sure that all the ETH calls you send kind of get wrapped up and like sandwiched into this weird compiled solidity thing, so that when you actually make make the calls they get sent off in parallel as one ETH call and it gets wrapped up in the multi-call contract. I'm assuming everyone here is everyone here familiar with multi-calls? I feel like yes. Okay perfect. The one problem with like multi-calls in general is like if you do a wait on each ETH call it can't batch those together so you do have to like kind of smush them all together in this really annoying way in how javascript deals with a wait async if you'll have like a good solution to this i'd love to hear that too um so one thing to keep in mind with multi-calls that in this work that's true for all multi-calls like message.sender is wrong um usually that doesn't matter in a view function. So and that's one thing that's missing here is like there should be view in there. It doesn't fit on the slides and that's why it's not there. So yes. As a quick example of like how you can like abuse the init. This is a very like like convoluted example or very like I don know, like a quick example. But basically, you have your constructor and in the last thing, you just put this like block of assembly and you're basically returning the actual data you want instead of the code that would be deployed, which is what a transaction usually does. So you can imagine the way you do this is you build your bytecode as if you were deploying a transaction, include no to address, and then you call the transaction as of its deployment. And so yes, please feel free to come up to me afterwards and ask for more information on anything in this talk. But I'm excited about this. There's a really cool things we can do with this. Anything that's a viewish that you don't need deployed contracts for is wonderful. So this is something I feel like everyone really needs to understand because it's so useful. Like people always open issues saying such and such isn't working and they're like I don't know why and they don't give you any meaningful information that you can like work with. So ethers has an event called debug and if you do like provider.on debug, it spits out a ton of data, way too much. You definitely want like a filter, but if you're doing CCIP read, it's a great way to kind of like debug what is going on with CCIP read, because it's a very complicated like back and forth all over the place. So it's nice to see, oh the URLs are coming back as not an array, or the URLs are including something they're not supposed to. Or if there's a failure, it tells you kind of like where in the CCIP stack things went awry so you can fix your contract and continue on. Same thing for JSON RPC. There's a lot of times where JSON RPC just returns wrong data, and it's kind of nice to be able to see why and what data you're getting back from the server. You can also just do normal accounting. A huge example, usually when I give this piece of, because people will say, sorry, I'm talking so fast. So a lot of times people will say, you know, I'm sending a bajillion requests to the network, I don't know why. They put this on, and then they see that there's a bunch of ETH chain IDs being sent to the network. So then they realize, oh, I need to put like a static network true in the JSONRPC provider. And then they literally just cut all their requests in half by looking at the debug for like 30 seconds, they see what's going on. And again, like any other analytics you desire, like you can really just examine what's going on. So this is probably the big chunk of the talk I want to cover, which is fetch hooking. So Ethers has its own fetch library called Fetch Request. And it's designed to be very flexible because there's a lot of weird things we can do in Ethereum. And it's designed to be hooked a lot. And so the most common hook that I recommend for a lot of people is this, wherever it went, maybe it's on the next slide. It's called get URL func. And so you can give it an alternate method of getting URL contents. So for example, now the defaults are in browser, it uses fetch. In Node.js, it uses HTTP and HTTPS lib. I mean, it'll be moving to the fetch in the near future. But you can do things like if you have a data URL, there's no distinction to the library, whether you're fetching a data URL or whether you're fetching a HTTPS URL or whatever it is. So this is useful. For example, a lot of NFTs have a URL property in the contract. So if you pass the result of that back into this, it doesn't matter whether they're using data URLs or whether they're using IPFS. It'll just kind of get forwarded, and you get back the information you wanted. You can also make your own weird... If you really want to do an obscure scheme, you want like weird colon slash slash does something, you can use this and you get an opportunity to kind of like intercept that and now you can implement weird colon slash slash to do whatever you want it to do. It's probably useful for like doing Android apps or like Universal deep linking and things like that. It's just there for people who want to do weird stuff. So for example like there's alternatives to IPFS that I don't know about, I don't currently support. For three lines of JavaScript you can now add support for a racknet or Skynet. Skynet, that's the one, yes. Also, so this is a great use of it, is hijacking for transparency. Now this is a very toy example, but basically this is hijacking the get URL funk so that every time a request is made to the internet, a pop-up shows up to the user saying, are you sure you want to allow inferior.io slash blah to execute? And if they hit no, then the whole thing is just killed and you could imagine for example having a checkbox in your thing saying you know don't warn about this domain again in which case inferior keeps working why this is super important and I think we need more people to start adopting these types of protections for the CC IP allows reading a contract to send you to some who knows what URL where they can like attach your address to your IP address, like your Ethereum address to your IP address and that sort of thing. And so you can also imagine like intentionally blocking it. If your app is not meant to show NFTs and someone's kind of using CCIP reads to like mine this data, you don't even need to present this to the user. You can just like stop it right then and there and say this contract is malicious or malicious adjacent, and so please go and decide whatever you want to do, however you want to process that sort of problem. And you can either set it globally so that you catch everything from any fetch request across all the ethers library or anything that uses the fetch result or you can just attach it to like one specific provider if that provider is something you want to like kind of gatekeep because maybe you're cutting you chain you don't trust or or that sort of thing yes and for security again I have a lot of like hijacking things because the hijacking is so useful and I really feel like there's so many cool things we can do with it. So, I mean, I don't have an actual example of how to connect to Tor up here, but you could imagine like every time you try sending a request to the web it like gets a chance to get wrapped up in Tor, onioned out and like comes back. So if you wanted to like build a more private in like MetaMask, If your MetaMask is using this library you can just send everything through Tor whether it's a JSON RPC request or whether it's a CCIP or whether it's looking up an avatar. If you use ENS to look up an avatar that returns a URL which points to a URL which points to another thing. It gives you a chance to kind of intercept all those steps forward it to the person you want it forward to or funnel it through a SOCKS5 proxy, or all those good things. Sorry, one second. And for example, if you have like bearer, like JWT, you could have one, like this bottom example, every time a URL goes out, the last step you do before it hits the network is it gets signed. You put your signature in there. And the nice thing about this get URL funk is it gets called whether it's, like the fetch result will automatically handle things like 301 redirects for you, or if there's a 429 throttle, it'll retry. And so on every single request to the network, you get this chance to like inject that like extra data you want. You can like keep the knots going, that sort of thing. I think there's one more example, which is mockery. Yes. So I use this a lot in ethers myself for the tests, but you can basically make a URL func that lies to the provider. So in this case, you can see, you build the JSONRPC provider, and it's always gonna return block 42 when you call get block number, because it kind of gets that chance to bypass the entire network thing and just gives you back that. So, for example, the fallback provider, for those that aren't familiar, it's a very complicated thing that has nests, requests. Okay, let me stack back for a second. requests, okay, let me stack back for a second. It connects to multiple backends simultaneously, randomly issuing a given request to a subset of those backends to look for coordination. So for example, if you want to call ENS and get the address for rickmu.eth, it'll call Infer and Alchemy. If they come back with the same answer, then you get that answer. If they differ, it's gonna like knock off maybe Anchor and it's gonna try finding like a coordination between the backends that agrees. So in the event that Anchor was hacked or in the event that Infera is down, you get like a cohesive result at the end that's kind of embedded by other, by a quorum of backends. So as you imagine testing this, it's very hard to test like, well, what happens if alchemy returns bad data and inferior returns like correct data, but this other thing does really weird gibberish or there's bad characters in the output. This makes it very easy to test what happens to provider in these types of situations. You can use it for your own stuff as well. For those that are familiar with NOC, it lets you do a lot of things that you do with NOC. Yes. So almost done. I'm trying to leave extra time as well for questions. But so this is just a very short thing. I feel like a lot of people don't realize the power of Etherscan. Etherscan has verified contracts. We all know that. It's awesome. We all love that effort we go through to verify a contract. Well, it's nice that once it's verified, you can just provider.getcontract, give it the contract address. It'll fetch your ABI, and it will automatically connect you to that contract, and you're good to go. After this, you could imagine doing like c.connect to a signer if you wanted to get like right access to it. But yes, I think we're getting close. If not the end, yes, aha. And so that is my quick talk on some of the hidden things I feel like are missing in a lot of, not even missing, a lot of things I feel like I want to see more people use. So yes. Thank you. Thank you, Richard. That was much shorter than I expected, but I also finished at 8 AM this morning, so... It's all right. Don't worry. Look, I don't think I did a proper job at introducing you. Oh, sorry, sorry. No, that's fine. So tell us, what is it you're doing? So, I mean, I work on a few projects. So Ethers.js, obviously, is like my passion I've been working on for ages. Oh, nice. How many people work on Ethers.js? Just me. Oh, wow. Just myself, yeah. I'm trying to recruit other help, but I'm also a little bit of a... I'm not a manager. I don't know how to delegate, and so it's hard to... That's your thing. But the other... This is your baby. This is my baby. Yes, exactly. And the other project I'm working on is Firefly for those that still haven't got one. Come find me today. It's like a hardware wallet. It's open source and all that sort of thing. Very cool. All right, you have a QR code here. Smash that question button, and we'll get started. Okay, let me refresh. Top question. Wait, I'm not on the right position. Okay, when ETH simulate V1 support? So I'm not even familiar with what that is. If somebody wants to open an issue and post a link to either an EIP, or is it a geth thing? You know what? Let's go to the next question question can you elaborate on using static network true okay excellent that one I can definitely elaborate on so basically when you connect to a network so if you're using for example metamask the network can just spontaneously change so ethers has to be ready for the network to spontaneously change if you get the nonce for for mainnet, the last thing you want to do is start preparing a transaction with mainnet nonce on Sepolia. Things are going to fail in horrible ways. You can imagine much worse things happening, like sending things to the wrong die address, for example. So ethers always like checks. But if you're connected to Infira, it's never changing. There's never a point in time where, like, mainnet.infira.io will return to you Sopolia data outside of, like, catastrophic events. And so you can basically specify in the options that the network is static and that you should not even bother trying to check for it again. Once you get it, just use what you have. Perfect. Thank you. Okay, I have the thing up and now we can go to the next one. Can the Etherscan contract retrieval also retrieve from other contract repository like Sourcefy? So it cannot now, but there's no reason it couldn't if somebody points me to more data about Sourcefy, like where the repository is. My guess is they don't run a back-end, so you might need to specify the contract address and a provider to connect to. But, I mean, that's like five lines of code. So, I mean, I'm just not familiar with a lot of these other services. There's just so much in the space to keep up with. So, for sure, open an issue on GitHub or come talk to me afterwards. If you're a Sourceify person trying to push your Sourceify thing, I fully endorse that, and I want you to come bug me to get added as well. Yes. That makes sense. The next question is cut in half, so we're going to skip it. Can you tell us how Etters is better than Veeam? So I feel like this is, I kind of expected a question along these lines. I'm a big fan in general of diversity. So it's not necessarily better. I feel it's very different. The big difference I see is VM is very much designed around functions, which is great for tree shaking, but I feel it makes things more difficult for developers. Ethers is very object-based. You can't tree shake a class in a meaningful way. So that's kind of like, you can only tree shake out the file or the object level. At the end of the day, I don't really worry too much with that. The thing is, I wrote Ethers for me. So it's what I use. It's kind of using the paradigms I care about. So I don't really have a lot to say about that. I mean I have not used VM other than like looking at it. I've talked to the guys like it's yeah it is yeah I've got nothing more to really to say about that. Let's just something specific feel free to be specific. So one of the challenge for developers is to get historical balances of ETH and L2 chains. What do you think could be the best way in the future to get these without an archival node in place? I mean, I can totally imagine a place where there's something like the graph, but for like historical data, we really need some sort of service probably to support that. And like the economic incentives around providing that data always mean that you're basically going to need like some sort of paid service like an affair or whatever unless I mean if it has brilliant ideas go for it um if there's a service that ethers can use for that please like tell me again but I feel like them the moral the stories tell me about it because I want to add these things if they exist but it's definitely something, it's not a service that I could write or host. Like, this is just petabytes of data that would be, well, it'd be gigabytes of data with petabytes of indexing into that data. It doesn't seem like the kind of stuff you can ship in ethers, but it's a service people should do. Right, and if it's a service that exists, like, tenderly, I will totally provide an Ethers way into it. Nice. Thank you. Can you elaborate on using static network? Oh, is this more than the last one? This one is the one that was voted. Okay. If you want to pick another one, go ahead. Which one would you like more? Oh, I mean, I thought I answered that one. Oh. Okay. Sorry, I didn't mark it as... Sorry. Okay. Is there I answered that one. Oh, okay. Sorry, I didn't mark it as... Sorry. Okay, is there a way to implement custom RPC calls? Some chains have non-standard ones. Absolutely. So if you have a JSON RPC provider, you just do .send, you give the eth method, and then you give it whatever eth method for that network takes. Oh, for sure. Like, this is the way you should be processing a lot of... Oh, there's a thing I should add to a slide. It's too late. I'll remember it for next time. But yes, for sure you can add custom, it's required. A lot of chains have their own exotic behaviors that are really useful to be able to access. OK, we'll get you where you were a bit early, so I'm going to take another one. I was going to say, I have 41 seconds left on there. It's OK. So you showed something about making requests over Tor. Why is it useful to make requests over Tor when you can't really run an Ethereum node over Tor? I mean, these serve different purposes, right? Like, if your avatar is being served on the Internet off of some web server, you might want to protect your IP address from being attached to that necessary avatar. I mean, I understand the sentiment of the question. It would be awesome if we could Torify like Ethereum, but there's still lots of like privacy value in talking over Tor. That's also like a toy example. You could imagine other weird transports where you're basically trying to send data over like a BLE network over top. Maybe you're inside a really busy venue like this and you can imagine having a BLE Firecast style communications protocol so you could implement that on top of that if you wished but I mean I'm still a big fan of Tor I think Tor needs I don't know whether funding is the right word they need something but Tor is awesome And so there's lots of privacy-focused things where Tor could be useful still. Richard, thank you for your talk. Thank you for your work. Frogbump. Thank you, thank you.
