Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get token balance with Ethereum RPC?

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?

like image 573
avp Avatar asked Jan 12 '18 14:01

avp


3 Answers

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

like image 108
LF00 Avatar answered Oct 24 '22 09:10

LF00


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.

like image 36
user94559 Avatar answered Oct 24 '22 11:10

user94559


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
like image 2
Furqan Siddiqui Avatar answered Oct 24 '22 10:10

Furqan Siddiqui