TriportRPC

eth_call

POSThttps://api.triport.io/v1/polygon/rpc

Executes a read-only smart-contract call against the current (or a historical) Polygon state, returning the raw result without creating a transaction or spending gas.

Polygonpolygon_read_rpcFree tier and up — free 15 rps · basic 20 rps · pro 100 rps · business 250 rps

eth_call runs a message call locally on a Polygon node and returns whatever the contract's code would return, without broadcasting a transaction, mining a block, or changing any state. It is the workhorse for reading on-chain data: token balances (balanceOf), allowances, pool reserves, oracle prices, and any other view/pure function or simulated state-changing call.

Because the call is executed in-memory against a chosen block, you get an instant, gas-free answer. Use it whenever you need to read contract state or simulate the outcome of a call before sending a real transaction. To actually broadcast a state change, use eth_sendRawTransaction instead.

Gotchas

  • The data field must be the ABI-encoded calldata — a 4-byte function selector followed by the 32-byte-padded arguments. Build it with a library (ethers/web3/viem) rather than by hand.
  • A reverting contract returns an error (with the revert reason when available), not an empty result. Always handle the error path.
  • Results reflect the state at the requested block tag. Omitting the tag means latest, which can change between calls.
  • Batch your reads. Calling eth_call once per token/account burns your rps budget fast. Route many reads through Multicall3 at 0xcA11bde05977b3631167028862bE2a173976CA11 (same address on Polygon) and collapse dozens of reads into a single eth_call.

Parameters

eth_call takes two positional params: a call object and a block tag.

Call objectobjectrequired
The transaction/call to execute (see fields below).
Block tagstringoptional
Block to execute against. Defaults to latest.
Call fieldsobject
tostring (address)required
Address of the contract being called.
fromstring (address)optional
Address the call is made from. Used by contracts that read msg.sender.
datastring (hex)optional
ABI-encoded calldata: 4-byte selector + encoded arguments.
valuestring (hex wei)optional
Amount of native MATIC to send with the simulated call.
Block tag valuesobject

Response

The result is the raw, ABI-encoded return value. Here 0x…2540be400 decodes to 10000000000 — i.e. 10,000 USDC (6 decimals). Decode it with your ABI to get a typed value.

jsonrpcstring
Always "2.0".
idnumber | string
Echoes the request id.
resultstring (hex)
ABI-encoded return data from the contract. 0x if the function returns nothing.

Errors

On failure the response carries an error object instead of result. See the shared errors reference for the full error envelope and the canonical meaning of each platform code.

CodeMessageWhen it happens
-32001trial_expiredThe free-trial period for this key has ended; upgrade to continue.
-32002tier_insufficientThe key's tier is below what the method requires. eth_call is available from the free tier, so this appears only if the key's scopes are restricted. Carries data.required_tier / data.upgrade_url.
-32003rate_limitedPer-second rate limit for your tier exceeded; check data.retry_after_sec, back off, and retry.
-32004subscription_expiredA previously active paid subscription has lapsed; renew to restore access.
-32005unauthorizedMissing, invalid, or revoked API key.
-32601method_unknownThe method name is misspelled or not part of the Polygon product. Carries data.chain and data.method.

Note: Rate limiting is enforced per-second per tier with burst headroom — there is no daily quota. Exceeding your tier's rps returns -32003 (rate_limited) with a data.retry_after_sec hint; back off and retry.

A reverting contract surfaces a platform error whose message includes the decoded revert reason when the contract provides one.

Examples

JavaScript (fetch)

const res = await fetch("https://api.triport.io/v1/polygon/rpc", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TRIPORT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "eth_call",
    params: [
      {
        to: "0x3c499c542cEF5E3811e1192ce70d8cc03d5c3359",
        data: "0x70a08231000000000000000000000000ab5801a7d398351b8be11c439e05c5b3259aec9b",
      },
      "latest",
    ],
  }),
});


const { result } = await res.json();
console.log("raw return:", result);
console.log("balance:", BigInt(result).toString());

TypeScript SDK (@triport/sdk)

import { Triport } from "@triport/sdk";
import { Interface } from "ethers";


const triport = new Triport({ apiKey: process.env.TRIPORT_API_KEY! });


const usdc = "0x3c499c542cEF5E3811e1192ce70d8cc03d5c3359";
const iface = new Interface(["function balanceOf(address) view returns (uint256)"]);


const result = await triport.polygon.rpc("eth_call", [
  { to: usdc, data: iface.encodeFunctionData("balanceOf", ["0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B"]) },
  "latest",
]);


const [balance] = iface.decodeFunctionResult("balanceOf", result);
console.log(balance.toString());

Python (triport-sdk)

import os
from triport import Triport
from eth_abi import decode


triport = Triport(api_key=os.environ["TRIPORT_API_KEY"])


usdc = "0x3c499c542cEF5E3811e1192ce70d8cc03d5c3359"
holder = "ab5801a7d398351b8be11c439e05c5b3259aec9b"
data = "0x70a08231" + holder.rjust(64, "0")


result = triport.polygon.rpc(
    "eth_call",
    [{"to": usdc, "data": data}, "latest"],
)


(balance,) = decode(["uint256"], bytes.fromhex(result[2:]))
print(balance)

Notes

  • Batching: wrap multiple reads in a single eth_call to Multicall3 (0xcA11bde05977b3631167028862bE2a173976CA11). One round trip, one rps charge, consistent block snapshot across every read.
  • Historical reads: pass a hex block number as the second param to read state as of that block (subject to node history retention).
  • Simulation: set from and value to simulate how a call would behave for a specific sender before sending it for real with eth_sendRawTransaction.
  • Estimating gas: to size a transaction rather than read its output, use eth_estimateGas.
  • Related reads: eth_getBalance for native MATIC balances, eth_getCode to confirm an address is a contract.