Skip to main content

EVM RPC costs

Advanced
Ethereum
Tutorial

Each call made to the EVM RPC canister costs cycles.

Costs

JSON-RPC requests typically cost between 10^8 and 10^9 cycles, which is equivalent to approximately $0.0001 - $0.001 USD.

Because the Candid-RPC methods of the EVM RPC canister use built-in retries and multiple providers, the amount of cycles required for each RPC call isn't predictable beforehand. The idea for these methods is to send a maximum cycles budget to perform the request.

The EVM RPC canister will continue retrying the request until it runs out of cycles sent with the request. This is important for requests such as eth_getLogs, where one request might return 100x as much data than the same request a few days earlier if there is a spike in smart contract activity. As a result, the optimal cycles budget is different for each use case. It is suggested to send 10_000_000_000 cycles as a starting point and adjust from there.

The following formula shows how to calculate the cycles cost for an RPC request:

(
5_912_000
+ 60_000 * nodes_in_subnet // Number of nodes in the subnet
+ 2400 * request_size // Size of the HTTP request in bytes
+ 800 * max_response_size // Maximum HTTP response size in bytes
) * nodes_in_subnet
* rpc_services // Number of RPC services used to check consistency

The total cost for an RPC request (assuming a 1kB request, 1kB response, 34-node subnet, and 1 XDR = $1.336610 USD) is ~ $0.00051 USD.

Note that the cost is multiplied by the number of RPC services used for the consistency logic. If you specify three different services, it will cost three times as much as a call to a single RPC provider.

In addition, it's necessary to send 10_000_000 * nodes_in_subnet * rpc_services additional cycles, which will be refunded, as they serve as a buffer for any future increases in third-party JSON-RPC API costs.

The EVM RPC canister automatically refunds any cycles sent beyond the cost of the RPC request, so it's possible to send more cycles than necessary without consequence. Sending extra cycles will also provide a budget to retry the request with a larger maximum response size for Candid-RPC methods such as eth_getLogs and eth_getBlockByNumber.

Collateral cycles

In addition to the cost of the RPC request itself, callers must also pass at least 0.00028 TC of "collateral cycles" to account for possible future downstream API price increases. The canister currently refunds all of these cycles, but this may change in the future.

Attaching the correct amount of cycles

To determine how many cycles need to be sent with your RPC call, you can use the requestCost query method. This is used to predict costs for calls to the request method:

`requestCost`

requestCost : (
source : JsonRpcSource,
jsonRequest : text,
maxResponseBytes : nat64
) -> (
Result<nat, RpcError>
) query;

This query method accepts the same arguments as the canister's request method and returns the number of cycles to send with an equivalent call.

Once you have determined how many cycles your call will need, you can send them in your call through a CDK or using dfx with the --with-cycles flag.

import EvmRpc "canister:evm_rpc";
import Cycles "mo:base/ExperimentalCycles";

Cycles.add<system>(1000000000);
let result = await EvmRpc.eth_getBlockByNumber(services, null, #Latest);

In order to accurately measure the HTTPS outcall cost and protect from an accidental large responses, the caller must specify the maximum expected number of bytes. Due to the potentially high cost of performing outcalls with a suboptimal max response size, it’s generally in the caller’s best interest to choose a value for maxResponseBytes on a case-by-case basis for each situation. Developers can determine this value by measuring the size of expected JSON responses from an API playground such as Alchemy Sandbox.

The Candid RPC methods use a built-in default response bytes, which you can override with the RpcConfig value.

You may choose to repeatedly call the request method with an increasingly large value for maxResponseBytes to handle variable response sizes. We defer this choice of strategy to the caller for raw JSON-RPC calls. For Candid-RPC convenience methods, the canister doubles the max response size and retries until the response size is sufficient, starting with a reasonable default for each RPC method. In contrast, the JSON-RPC canister only ever makes one request, deferring the retry logic to the caller. It’s worth noting that the caller essentially pays for each outcall as though they are sending these requests from their own canister.

The EVM RPC canister retries the call if:

  • There are enough cycles left that have been sent by the caller.

  • The call fails due to maxResponseBytes being set too low. Each RPC method has a built-in default maxResponseBytes setting that can be overridden.

Additionally, the RpcConfig parameter supports an optional responseSizeEstimate which can be fine-tuned to reduce the cost of the RPC requests.

Next steps

View some sample projects using the EVM RPC canister.