Get token balance with Ethereum RPC?

11,069

Solution 1

To get token balance with eth_call you need to and data parameter. to is contract address, here we need to generate the data parameter. As the doc eth_call says,

data: DATA - (optional) Hash of the method signature and encoded parameters. For details see Ethereum-Contract-ABI

Take this EOS token transaction as a example.

Contract address:0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0

Token Holder address:0x0b88516a6d22bf8e0d3657effbd41577c5fd4cb7

You can see the contract code here.

contract ERC20 {
    function totalSupply() constant returns (uint supply);
    function balanceOf( address who ) constant returns (uint value);
    function allowance( address owner, address spender ) constant returns (uint _allowance);

    function transfer( address to, uint value) returns (bool ok);
    function transferFrom( address from, address to, uint value) returns (bool ok);
    function approve( address spender, uint value ) returns (bool ok);

    event Transfer( address indexed from, address indexed to, uint value);
    event Approval( address indexed owner, address indexed spender, uint value);
}

Function Selector

>>> from web3 import Web3
>>> Web3.sha3("balanceOf(address)")
HexBytes('0x70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be')

Take the first four bytes 70a08231

Argument Encoding

address: equivalent to uint160, except for the assumed interpretation and language typing.

int: enc(X) is the big-endian two's complement encoding of X, padded on the higher-order (left) side with 0xff for negative X and with zero bytes for positive X such that the length is a multiple of 32 bytes.

Padding the 20 bytes token address to 32 bytes with 0 to token holder address:

0000000000000000000000000b88516a6d22bf8e0d3657effbd41577c5fd4cb7

Then concat the function selector and encoded parameter, we get data parameter:

0x70a082310000000000000000000000000b88516a6d22bf8e0d3657effbd41577c5fd4cb7

Make the request with:

curl -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to": "0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0", "data":"0x70a082310000000000000000000000000b88516a6d22bf8e0d3657effbd41577c5fd4cb7"}, "latest"],"id":67}' -H "Content-Type: application/json" http://127.0.0.1:8545/

here is the curl result (You may get different answer here, as there may be some transaction with this address done after my polling the request)

{"jsonrpc":"2.0","id":67,"result":"0x00000000000000000000000000000000000000000000014a314d9ff9b20b9800"}

You can change convert hex format balance to decimal

>>> 0x00000000000000000000000000000000000000000000014a314d9ff9b20b9800
6090978215900000000000

Check the result,

enter image description here

Solution 2

When calling a Solidity contract function, in general, data should be the following, encoded as a hex string:

  1. The "function selector," which is the first four bytes of the keccak-256 hash of the signature of the function you're calling.
  2. The ABI-encoded arguments to the function you're calling.

The function signature for an ERC20 token's balanceOf is balanceOf(address). The keccak-256 hash is 70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be, so the first four bytes are 70a08231.

The function only takes a single parameter: the address of the account whose balance you're trying to look up. To ABI-encode it, simply left-pad it with zeros until it's 32 bytes long. Since addresses are 20 bytes, this means adding 12 bytes of zeros (or 24 characters in hex).

So the full data field should be "0x70a08231" + "000000000000000000000000" + address.

Solution 3

May I recommend a proper ERC20 library for PHP that I have developed myself.

https://www.furqansiddiqui.com/libraries/erc20-php/

https://github.com/furqansiddiqui/erc20-php

sample code to retrieve balance:

<?php
$geth = new EthereumRPC('127.0.0.1', 8545);
$erc20 = new \ERC20\ERC20($geth);

// Pass ERC20 contract address as argument below
$token = $erc20->token('0xd26114cd6EE289AccF82350c8d8487fedB8A0C07');

var_dump($token->name()); # string(8) "OMGToken"
var_dump($token->symbol()); # string(3) "OMG"
var_dump($token->decimals()); # int(18)

var_dump($token->balanceOf('0x...')); // Enter ethereum address here
Share:
11,069
avp
Author by

avp

Updated on June 25, 2022

Comments

  • avp
    avp almost 2 years

    how display balance of token through Ethereum RPC?

    $id = 0;
    $data = array();
    $data['jsonrpc'] = '2.0';
    $data['id'] = $id++;
    $data['method'] = 'eth_call';
    $data['params'] = [['from' => '0x0...', 'to' => '0x0...', 'data' => 'contract byte code here 0x0...'], 'latest'];
    
    $ch = curl_init();
    ...
    

    Return:

    {"jsonrpc":"2.0","id":0,"result":"0x"}
    

    What to do next? Call contract method balanceOf? How to do that?