> For the complete documentation index, see [llms.txt](https://docs.chainrpc.io/chainrpc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.chainrpc.io/chainrpc/networks/ethereum/how-to/interact-with-erc-20-tokens.md).

# Interact with ERC-20 tokens

[ERC-20](https://eips.ethereum.org/EIPS/eip-20) is a simple token standard and the most common contract type on Ethereum.

You can:

* [Send ERC-20 transactions](#sending-transactions) using `eth_sendRawTransaction`.
* [Observe event logs of mined ERC-20 transactions](#mined-transactions) using `eth_getLogs`.
* Follow [this tutorial](broken://pages/0vvvf8FUroJuyIIFdMAL) to retrieve the balance of ERC-20 tokens.
* Follow [this tutorial](broken://pages/qa1t4Rj2GGuIumeP4mtF) to track ERC-20 token transfers.

## ERC-20 token functions and events

An ERC-20 token must implement the following functions:

* `totalSupply()` - Returns the total token supply.
* `balanceOf(owner)` - Returns the account balance of another account with address `owner`.
* `allowance(owner, spender)` - Returns the amount which `spender` is still allowed to withdraw from `owner`.
* `transfer(to, value)` - Transfers `value` amount of tokens to address `to.`
* `approve(spender, value)` - Allows `spender` to withdraw from your account multiple times, up to the `value` amount.
* `transferFrom(from, to, value)` - Transfers `value` amount of tokens from address `from` to address `to`.

At certain times, an ERC-20 token also must emit the following events:

* `Transfer(from, to, value)` - Must trigger when tokens are transferred, including zero value transfers.
* `Approval(owner, spender, value)` - Must trigger on any successful call to `approve(spender, value)`.

View [EIP-20](https://eips.ethereum.org/EIPS/eip-20) for more details about how these functions work and when to emit these events.

## **Send transactions** <a href="#sending-transactions" id="sending-transactions"></a>

Use [`eth_sendRawTransaction`](broken://pages/V3saeD5ILKgu0hXM6XUn) to send ERC-20 token transactions.

The JSON-RPC format expects `eth_sendRawTransaction` to have a specific data field format that requires normalizing the `Transfer` function to a short [function selector](https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector). To do this, set the parameters for the function and run it through Ethereum’s [sha3 keccak hash](https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector):

{% tabs %}
{% tab title="Example node console request" %}

```javascript
web3.sha3('Transfer(address,address,uint256)')[0..4]
```

{% endtab %}

{% tab title="Example JS result" %}

```javascript
0x70a08231
```

{% endtab %}
{% endtabs %}

The first four bytes of this hash comprise its four-byte signature. Take this four-byte signature, pad it with zeros, and package this information into a data string. Then sign the transaction and send it using `eth_sendRawTransaction`:

{% tabs %}
{% tab title="Example curl HTTPS request" %}

```bash
curl https://eth.chainrpc.io/v3/YOUR-API-KEY \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params": ["0xf869018203e882520894f17f52151ebef6c7334fad080c5704d77216b732881bc16d674ec80000801ba02da1c48b670996dcb1f447ef9ef00b33033c48a4fe938f420bec3e56bfd24071a062e0aa78a81bf0290afbc3a9d8e9a068e6d74caa66c5e0fa8a46deaae96b0833"],"id":1}'
```

{% endtab %}

{% tab title="Example JSON result" %}

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

{% endtab %}
{% endtabs %}

## **Observe logs of mined transactions** <a href="#mined-transactions" id="mined-transactions"></a>

When a transaction is mined, event logs are published for public viewing.

Once the event logs are published, you can execute [`eth_getLogs`](broken://pages/MdfIp73c68wfJvxjQg9j) to investigate what changed relative to the events that you care about, and react to them.

{% hint style="success" %}
For example, an event ticketing service that wants to issue off-chain tickets based on crypto payments can use `eth_getLogs` to find payments to their address, and react to these events by processing some logic in their backend servers to issue tickets to users.
{% endhint %}

The following example uses `eth_getLogs` on the DAI ERC-20 Solidity contract [`0x6B175474E89094C44Da98b954EedeAC495271d0F`](https://etherscan.io/address/0x6b175474e89094c44da98b954eedeac495271d0f#code):

{% tabs %}
{% tab title="Example curl HTTPS request" %}

```bash
curl https://eth.chainrpc.io/v3/YOUR-API-KEY \
    -X POST \
    -H "Content-Type: application/json" \
    -d {"jsonrpc":"2.0","method":"eth_getLogs","id":1,"params":[{"fromBlock":"Ox91F37C","toBlock":"0x91F37C","topics":[ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x000000000000000000000000ee25e1ba53c225d250861c8e5a9a3e0fe19c790e", "0x000000000000000000000000dfbaf3e4c7496dad574a1b842bc85b402bdc298d" ],"address":"0x6B175474E89094C44Da98b954EedeAC495271d0F"}]}
```

{% endtab %}

{% tab title="Example JSON result" %}

<pre class="language-json"><code class="lang-json">{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
<strong>    {
</strong>      "address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
      "topics": [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x000000000000000000000000ee25e1ba53c2250250861c8e5a9a3e0fe19c790e",
        "0x000000000000000000000000dfbaf3e4c7496dad574a1b842bc85b402bdc298d"
      ],
      "data": "0x00000000000000000000000000000000000000000000041f900d25d6693623a6",
      "blockNumbern": "0x91F37C"
    }
  ]
}
</code></pre>

{% endtab %}
{% endtabs %}

In this example request, the parameters `fromBlock` and `toBlock` specify the hexadecimal block number to retrieve logs from.

{% hint style="info" %}
If `fromBlock` and `toBlock` are omitted, `eth_getLogs` returns the *entire* chain history by default. Infura has a cap on requests of 10,000 events per query. We recommend requesting a single block, as in this example, and to do that for each mined block.
{% endhint %}

This request tells the blockchain to retrieve event logs related to address `0x6B175474E89094C44Da98b954EedeAC495271d0F` emitted in block `0x91F37C` that matches topics `0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef`, `0x000000000000000000000000ee25e1ba53c225d250861c8e5a9a3e0fe19c790e` and  `0x000000000000000000000000dfbaf3e4c7496dad574a1b842bc85b402bdc298d`.

The response returned for this request is an array of events. In this example, only one event for one address matches the specified topics.

### **Topics**

Topics are events emitted by smart contracts. Looking at the source code of the original contract [`0x6B175474E89094C44Da98b954EedeAC495271d0F`](https://etherscan.io/address/0x6b175474e89094c44da98b954eedeac495271d0f#code) used in this example, there are two event signatures that could be associated with it on lines 94 and 95:

```solidity
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
event Transfer(address indexed from, address indexed to, uint tokens);
```

To find out which topic (event) it actually was, create the [function selector](https://docs.soliditylang.org/en/develop/abi-spec.html#function-selector) of the event and take the [sha3 keccak hash](https://docs.soliditylang.org/en/develop/abi-spec.html#function-selector) of it. Let’s try the event on line 94:

{% tabs %}
{% tab title="Example node console request" %}

```javascript
web3.sha3('Approval(address,address,uint256)')
```

{% endtab %}

{% tab title="Example JS result" %}

```javascript
0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925
```

{% endtab %}
{% endtabs %}

The resulting hash doesn’t match the hash provided in the initial request response. Now let’s try the event on line 95 of the contract:

{% tabs %}
{% tab title="Example node console request" %}

```javascript
web3.sha3('Transfer(address,address,uint256)')
```

{% endtab %}

{% tab title="Example JS result" %}

```javascript
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
```

{% endtab %}
{% endtabs %}

The resulting hash matches the hash provided in the initial request response. Now you know that `0xddf25` is the transfer event in this example.

### **Data** <a href="#more-event-logs" id="more-event-logs"></a>

The `data` field in the request response refers to all the "non-indexed stuff" captured in the events. In this example, for the transfer topic, `data` represents the number of tokens that were transferred. That is, `0x41f900d25d6693623a6` or 19471.6949921 DAI tokens were transferred from `ee25e1ba53c225d250861c8e5a9a3e0fe19c790e` to `dfbaf3e4c7496dad574a1b842bc85b402bdc298d`.
