# eth_call - Plasma RPC Method

Executes a new message call immediately without creating a transaction on Plasma. Used for reading smart contract state.

> **Why Plasma?** Build on an EVM Layer 1 for stablecoin payments with PlasmaBFT consensus and Reth execution with 1 second blocks, XPL gas, full EVM JSON-RPC, and debug plus txpool on Dwellir.

## When to Use This Method

The `eth_call` method serves these key scenarios for payment app developers, wallet teams, and teams shipping Solidity contracts for dollar transfers:

- **Read smart contract state** - Execute view and pure functions to query token balances, DeFi positions, and protocol data without spending gas
- **Simulate transactions** - Test contract interactions before submitting them on-chain, avoiding failed transactions and wasted gas costs
- **Multi-call aggregator queries** - Batch multiple read calls into a single request using multicall contracts, reducing API overhead on Plasma
- **MEV and arbitrage analysis** - Simulate transaction bundles to evaluate profitable opportunities before execution on stablecoin transfers, payment apps, and wallets that need 1 second confirmation

## Common Use Cases

### 1. Read ERC20 Token Balance

Query an ERC20 token contract to retrieve the balance for a specific wallet address using the `balanceOf(address)` function selector encoded as calldata. The selector is derived from the first 4 bytes of keccak256("balanceOf(address)"), followed by the 32-byte zero-padded address argument.

```javascript
import { JsonRpcProvider } from 'ethers';

const provider = new JsonRpcProvider('https://api-plasma-mainnet.n.dwellir.com/YOUR_API_KEY');
const tokenAddress = '0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb';
const walletAddress = '0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb';

const balanceSelector = '0x70a08231' + walletAddress.slice(2).padStart(64, '0');

async function getTokenBalance() {
  const result = await provider.call({
    to: tokenAddress,
    data: balanceSelector
  });
  console.log('Balance (raw):', BigInt(result).toString());
  return result;
}

getTokenBalance();
```

### 2. Query DeFi Protocol State

Read protocol reserves, price oracles, or user positions from DeFi contracts on Plasma. Each protocol exposes view functions that let you inspect pool state without modifying it - ideal for building analytics dashboards and trading bots.

```javascript
import { JsonRpcProvider, Interface } from 'ethers';

const provider = new JsonRpcProvider('https://api-plasma-mainnet.n.dwellir.com/YOUR_API_KEY');

const poolAbi = [
  'function getReserves() view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestamp)'
];
const poolInterface = new Interface(poolAbi);
const poolAddress = '0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb';

async function getPoolReserves() {
  const data = poolInterface.encodeFunctionData('getReserves');
  const result = await provider.call({ to: poolAddress, data });
  const decoded = poolInterface.decodeFunctionResult('getReserves', result);
  console.log('Reserve 0:', decoded[0].toString());
  console.log('Reserve 1:', decoded[1].toString());
  return decoded;
}

getPoolReserves();
```

### 3. Simulate a Swap Before Execution

Before committing a token swap, call the router contract's quote function to calculate the expected output. This lets you validate slippage tolerance and compare rates across DEXes without risking gas on a failed trade.

```javascript
import { JsonRpcProvider, Interface, parseEther } from 'ethers';

const provider = new JsonRpcProvider('https://api-plasma-mainnet.n.dwellir.com/YOUR_API_KEY');
const routerAddress = '0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb';

const routerAbi = [
  'function getAmountsOut(uint amountIn, address[] calldata path) view returns (uint[] amounts)'
];
const routerInterface = new Interface(routerAbi);

async function simulateSwap(amountIn, tokenIn, tokenOut) {
  const data = routerInterface.encodeFunctionData('getAmountsOut', [
    parseEther(amountIn),
    [tokenIn, tokenOut]
  ]);
  const result = await provider.call({ to: routerAddress, data });
  const decoded = routerInterface.decodeFunctionResult('getAmountsOut', result);
  console.log('Expected output:', decoded[0][1].toString());
  return decoded[0][1];
}

simulateSwap('1.0', '0xTokenA...', '0xTokenB...');
```

## Best Practices

- Use `latest` for current-state reads and `pending` for pre-confirmation simulation on Plasma
- Encode function selectors correctly: take the first 4 bytes of the keccak256 hash of the function signature
- Handle revert errors gracefully by parsing the revert reason from the error response data
- For batch reads, use multicall contracts to combine multiple `eth_call` requests into a single RPC call
- `eth_call` does not consume gas, making it ideal for unlimited read queries on Plasma

## Request Parameters

- `from` (`DATA, optional`): 20-byte address executing the call
- `to` (`DATA, required`): 20-byte contract address
- `gas` (`QUANTITY, optional`): Gas limit for the call
- `gasPrice` (`QUANTITY, optional`): Gas price in wei
- `value` (`QUANTITY, optional`): Value to send in wei
- `data` (`DATA, required`): Encoded function call data
- `blockParameter` (`QUANTITY|TAG, required`): Block number or tag

## Request Example

```json
{
  "jsonrpc": "2.0",
  "method": "eth_call",
  "params": [
    {
      "to": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
      "data": "0x70a08231000000000000000000000000B8CE59FC3717ada4C02eaDF9682A9e934F625ebb"
    },
    "latest"
  ],
  "id": 1
}
```

## Response Fields

- `result` (`DATA, required`): The return value of the executed contract function

## Successful Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
}
```

## Code Examples

cURL
JavaScript
Python
Go

```bash
# Call ERC20 balanceOf function
curl -X POST https://api-plasma-mainnet.n.dwellir.com/YOUR_API_KEY \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "eth_call",
    "params": [{
      "to": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
      "data": "0x70a08231000000000000000000000000B8CE59FC3717ada4C02eaDF9682A9e934F625ebb"
    }, "latest"],
    "id": 1
  }'
```

```javascript
import { JsonRpcProvider, Contract } from 'ethers';

const provider = new JsonRpcProvider('https://api-plasma-mainnet.n.dwellir.com/YOUR_API_KEY');

// ERC20 ABI for common functions
const ERC20_ABI = [
  "function balanceOf(address owner) view returns (uint256)",
  "function allowance(address owner, address spender) view returns (uint256)",
  "function totalSupply() view returns (uint256)",
  "function decimals() view returns (uint8)",
  "function symbol() view returns (string)"
];

// Read ERC20 token balance
async function getTokenBalance(tokenAddress, walletAddress) {
  const contract = new Contract(tokenAddress, ERC20_ABI, provider);
  const balance = await contract.balanceOf(walletAddress);
  const decimals = await contract.decimals();
  const symbol = await contract.symbol();

  return {
    raw: balance.toString(),
    formatted: (Number(balance) / Math.pow(10, decimals)).toFixed(4),
    symbol: symbol
  };
}

// Direct eth_call
async function directCall(to, data) {
  const result = await provider.call({ to, data });
  return result;
}
```

```python
from web3 import Web3

w3 = Web3(Web3.HTTPProvider('https://api-plasma-mainnet.n.dwellir.com/YOUR_API_KEY'))

def get_erc20_balance(token_address, wallet_address):
    # balanceOf(address) selector
    function_signature = "balanceOf(address)"
    function_selector = w3.keccak(text=function_signature)[:4].hex()

    # Encode address parameter
    encoded_address = wallet_address[2:].lower().zfill(64)
    data = function_selector + encoded_address

    # Make the call
    result = w3.eth.call({
        'to': token_address,
        'data': data
    })

    return int(result.hex(), 16)

balance = get_erc20_balance(
    '0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb',
    '0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb'
)
print(f'Balance: {balance}')
```

```go
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/ethereum/go-ethereum"
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/ethclient"
)

func main() {
    client, err := ethclient.Dial("https://api-plasma-mainnet.n.dwellir.com/YOUR_API_KEY")
    if err != nil {
        log.Fatal(err)
    }

    contractAddress := common.HexToAddress("0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb")
    data := common.FromHex("0x70a08231000000000000000000000000B8CE59FC3717ada4C02eaDF9682A9e934F625ebb")

    msg := ethereum.CallMsg{
        To:   &contractAddress,
        Data: data,
    }

    result, err := client.CallContract(context.Background(), msg, nil)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Result: 0x%x\n", result)
}
```

## Related Methods

- [`eth_estimateGas`](https://www.dwellir.com/docs/plasma/eth_estimateGas) - Estimate gas for transaction
- [`eth_sendRawTransaction`](https://www.dwellir.com/docs/plasma/eth_sendRawTransaction) - Send actual transaction
