eth_call - Arbitrum

Executes a new message call immediately without creating a transaction on the block chain.

Don’t have an API key?

Start using this API in your app today.

This is one of the most commonly used API calls. It is used to read from the blockchain which includes executing smart contracts but does not publish anything to the blockchain. This call does not consume any Ether.

We can call any function of a smart contract using the eth_call method and it returns us any data that the function returns (in hex format). For read-only functions, it returns what the read-only function returns. For functions that change the state of the contract, it executes that transaction locally and returns any data returned by the function.

Calling the read-only function is a common use case because all read-only functions return something that we can read using this method.

Use cases for eth_call

eth_call is used to call read-only functions of a smart contract. For example, calling the balanceOf function of an ERC20 token contract.

🚧

Starting from Geth 1.9.13, eth_callwill check the balance of the sender (to make sure that the sender has enough gas to complete the request) before executing the call when one of the following conditions is true:

  1. the gas_price parameter is populated, or
  2. the contract function being called (i.e. in data modifies blockchain state)\

In these two cases, even though the eth_call requests don't consume any gas, the from address must have enough gas to execute the call as if it were a write transaction because eth_call is being used to simulate the transaction.

Parameters

  1. Object - The transaction call object

    • from: DATA, 20 Bytes - (optional) The address the transaction is sent from.
    • to: DATA, 20 Bytes - The address the transaction is directed to.
    • gas: QUANTITY - (optional) Integer of the gas provided for the transaction execution. eth_call consumes zero gas, but this parameter may be needed by some executions. NOTE: this parameter has a cap of 550 million gas per request. Reach out to us at [email protected] if you want to increase this limit!
    • gasPrice: QUANTITY - (optional) Integer of the gasPrice used for each paid gas.
    • value: QUANTITY - (optional) Integer of the value sent with this transaction
    • data: DATA - (optional) Hash of the method signature and encoded parameters. For details see Ethereum Contract ABI
  2. QUANTITY|TAG - integer block number, or the string "latest", "earliest" or "pending" (see the default block parameter), OR the blockHash (in accordance with EIP-1898) NOTE: the parameter is an object instead of a string and should be specified as: {"blockHash": "0x<some-hash>"}. Learn more here.

  3. Object - State override set
    The State Override Set option allows you to change the state of a contract before executing the call. This means you can modify the values of variables stored in the contract, such as balances and approvals for that call without actually modifying the contract on the blockchain.

    In more technical terms, the state override set is an optional parameter that allows executing the call against a modified chain state. It is an address-to-state mapping, where each entry specifies some state to be overridden prior to executing the call. Each address maps to an object containing:

FIELDTYPEBYTESDESCRIPTION
balanceQuantity<32Fake balance to set for the account before executing the call.
nonceQuantity<8Fake nonce to set for the account before executing the call.
codeBinaryanyFake EVM bytecode to inject into the account before executing the call.
stateObjectanyFake key-value mapping to override all slots in the account storage before executing the call.
stateDiffObjectanyFake key-value mapping to override individual slots in the account storage before executing the call.

Override Example:

Here's a simple code snippet in JavaScript that shows how you can use the State Override Set to mock an approval for a token transfer:

// Import the ethers.js library
const ethers = require("ethers");

// The address of the DAI token contract
const dai = "0x6b175474e89094c44da98b954eedeac495271d0f";

// The address of the sender
const fromAddr = "0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe";

// The address of the recipient
const toAddr = "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5";

// The allowance slot on the DAI contract (this may differ from contract to contract)
const slot = 3; 

// Use the solidityKeccak256 function from the ethers.js library to calculate the index for the allowance mapping
const temp = ethers.utils.solidityKeccak256(
  ["uint256", "uint256"],
  [fromAddr, slot]
);
const index = ethers.utils.solidityKeccak256(
  ["uint256", "uint256"],
  [toAddr, temp]
);

// The stateDiff object to mock an approval
const stateDiff = {
  [dai]: {
    stateDiff: {
      [index]: ethers.constants.MaxUint256.toHexString(), // setting the allowance to the max value of uint256
    },
  },
};

// Create an instance of the Ethereum provider
const provider = new ethers.providers.JsonRpcProvider("Your-Alchemy-API-URL");

// The parameters for the eth_call method
const callParams = [
  {
    to: dai,
    data: "0xdd62ed3e..." // The method signature and arguments for the call
  },
  "latest"
];

// Call the contract method without state overrides
const call1 = await provider.send("eth_call", callParams);

// Call the contract method with state overrides
const call2 = await provider.send("eth_call", [...callParams, stateDiff]);

// Log the results of both calls
console.log(call1); 
console.log(call2);

Code Explanation:

  • We first import the ethers.js library, which provides a convenient set of tools for working with EVM chains.
  • Next, we define the address of the DAI token contract and the addresses of the sender and recipient.
  • We then calculate the index for the allowance mapping in the token contract. This involves using the solidityKeccak256 function from the ethers.js library to calculate a unique identifier for the mapping based on the sender and recipient addresses.
  • The stateDiff object is created to mock an approval, which is done by setting the state of the index in the allowance mapping to the maximum possible value (ethers.constants.MaxUint256).
  • An instance of the Ethereum provider is created. This provider will be used to make calls to the Ethereum network.
  • The callParams constant is created that specifies the parameters for the eth_call method.
  • The contract method is called without state overrides and the result is stored in the call1 constant.
  • The contract method is called with state overrides and the result is stored in the call2 constant.
  • The results of both calls are logged to the console.

The State Override option is mainly used for testing purposes, as it allows developers to temporarily modify the state of the chain to simulate specific scenarios and test the behavior of smart contracts.

❗️

Note

eth_call has a timeout restriction at the node level. Batching multiple eth_call together on-chain using pre-deployed smart contracts might result in unexpected timeouts that cause none of your calls to complete. Instead, consider serializing these calls, or using smaller batches if they fail with a node error code.

params: [
    {
        "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
        "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
        "gas": "0x76c0",
        "gasPrice": "0x9184e72a000",
        "value": "0x9184e72a",
        "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
    }, 
    "latest"
]

Returns

DATA - the return value of the executed contract.

Example

Request

// Setup: npm install alchemy-sdk
// Github: https://github.com/alchemyplatform/alchemy-sdk-js
import { Network, Alchemy } from "alchemy-sdk";

// Optional config object, but defaults to demo api-key and eth-mainnet.
const settings = {
  apiKey: "demo", // Replace with your Alchemy API Key.
  network: Network.ETH_MAINNET, // Replace with your network.
};
const alchemy = new Alchemy(settings);

// Make a sample eth_call
alchemy.core
  .call({
    to: "0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41",
    gas: "0x76c0",
    gasPrice: "0x9184e72a000",
    data: "0x3b3b57debf074faa138b72c65adbdcfb329847e4f2c04bde7f7dd7fcad5a52d2f395a558",
  })
  .then(console.log);
// Installation instructions: https://docs.ethers.io/v5/getting-started/#installing

async function main() {
   const { ethers } = require("ethers");
   
	// Replace with your Alchemy API key:
	const apiKey = "demo";

	// Initialize an ethers instance
	const provider = new ethers.providers.AlchemyProvider("homestead", apiKey);

	// Query the blockchain (replace example parameters)
    const data = await provider.call(
	    {
	        "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
	        "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
	        "gas": "0x76c0",
	        "gasPrice": "0x9184e72a000",
	        "value": "0x9184e72a",
	        "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
	    }, 
	    "latest"
	); 
    
	// Print the output to console
	console.log(data);
   }

main()
# Installation Instructions: https://web3py.readthedocs.io/en/latest/quickstart.html#installation

from web3 import Web3, HTTPProvider

#Replace with your Alchemy API key:
apiKey = "demo"

# Initialize a Web3.py instance
web3 = Web3(Web3.HTTPProvider('https://eth-mainnet.g.alchemy.com/v2/'+apiKey))

# Query the blockchain (replace example parameters)
data = web3.eth.call({
		'value': 0, 
		'gas': 21736, 
		'maxFeePerGas': 2000000000, 
		'maxPriorityFeePerGas': 1000000000, 
		'to': '0xc305c90',
		'data': '0x477a5c98'
		}) 

# Print the output to console
print(data)
curl https://eth-mainnet.g.alchemy.com/v2/your-api-key \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_call","params":[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155","to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567","gas": "0x76c0","gasPrice": "0x9184e72a000","value": "0x9184e72a","data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"}, "latest"],"id":1}'
URL: https://eth-mainnet.g.alchemy.com/v2/your-api-key
RequestType: POST
Body: 
{
    "jsonrpc":"2.0",
    "method":"eth_call",
    "params":[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155","to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567","gas": "0x76c0","gasPrice": "0x9184e72a000","value": "0x9184e72a","data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"}, "latest"],
    "id":1
}

Result

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x"
}
Language
URL