EVM RPC Canister

I would like to share some rough thoughts after using the EVM RPC canister a bit and building examples in Azle (TypeScript/JavaScript CDK).

First off, I call into question the need for the EVM RPC canister if you have a library like Ethers.js, as long as the EVM RPC canister does not have a direct integration with Ethereum and simply relies on underlying RPC providers. I would have to double-check to be certain, but I remember reading while building my examples, which use Ethers.js, that Ethers.js has a provider that will send requests to mulitple RPC providers and essentially come to consensus on their results. If that’s the case, isn’t that exactly what the EVM RPC canister is doing? Then what benefit does the canister have if Ethers.js is fully available to the developer? Seems a much simpler and more standard experience to just use a library that already exists.

With that being said, perhaps not all languages available on ICP will have access to a nice library like Ethers.js. Even if that’s the case, I call into question why the EVM RPC canister is using Candid as the main interface language for this functionality. It’s quite complicated and confusing to use, and especially to teach to someone new to ICP. Wouldn’t it be better to just create an HTTP canister that acts identically to the other RPC providers? Not only could canisters within ICP interact with it using an HTTP API (for example Azle canisters can use fetch and icp:// and probably soon https:// to do cross-canister calls), but also we could expose this API to the internet. Perhaps while it just proxies other providers it might not be such a good idea, but if we ever get a more direct integration this could possibly be the most secure and transparent Ethereum JSON RPC provider in existence.

In short…can we embrace HTTP for the EVM RPC canister? And do we even need the canister (assuming a non-direct integration) in the presence of libraries like Ethers.js?

In shorter short: make the EVM RPC canister a true Ethereum JSON RPC API provider, just use HTTP.

Hi @lastmjs,

I agree with everything you’ve stated above and made a similar case to use libraries in place of a canister earlier on in development. After looking deeply into this problem, our conclusion was that although libraries such as Ethers.js exist, we also wanted a solution that would work consistently across all CDKs without requiring callers to configure their own API keys.

I would have to double-check to be certain, but I remember reading while building my examples, which use Ethers.js, that Ethers.js has a provider that will send requests to mulitple RPC providers and essentially come to consensus on their results.

If I understand correctly, this refers to the FallbackProvider in Ethers.js. There are certainly situations where it would make sense to use this over the EVM RPC canister.

The main reason to use the canister from a TypeScript project is the managed API keys. Default and free API keys often have an IP-based rate limit, which can become a problem if another project is running on the same subnet. In other words, Ethers.js would be ideal for those who are willing to pay for their own provider API keys.

With that being said, perhaps not all languages available on ICP will have access to a nice library like Ethers.js.

This is another big reason. To my knowledge, the ethers-providers Rust crate does not contain a way to check for agreement between providers. Motoko currently doesn’t have anything equivalent to Ethers at all, so the goal is to have a language-agnostic, batteries-included default solution. That being said, there are plenty of situations where it makes sense to use a library, especially for larger-scale Ethereum integrations.

Wouldn’t it be better to just create an HTTP canister that acts identically to the other RPC providers?

At first glance, this seems like a great solution. The reasoning for initially using a Candid interface is that we need to charge for HTTP outcalls. We could introduce ways to do this using our own API keys and prepayment, but this quickly becomes very complex compared to passing cycles with a canister call. However, I see your point and think that we could eventually offer this as an alternate way to make RPC requests.

Hopefully this makes sense! Let me know if you’d like any further clarification.

2 Likes

I wonder if future ICRC improvements, such as pre-signed payments, or even ERC tokens with approve/transferFrom could allow some kind of nice payment integration in the future.

But I am also talking about exposing the HTTP interface to other canisters. Soon Azle canisters will be able to use fetch and https:// URLs to talk directly to canisters that expose the http_request and http_request_update methods…it might be nice for the EVM RPC canister to expose these methods now, as cross-canister calls would still work with them.

1 Like

Makes sense! Doing this properly will require some time. I’ll add the HTTP interface to the backlog so we can decide how to prioritize this.

2 Likes

This would be awesome and probably the default way that we teach and document for Azle and eventually Kybra users