ethereum-php
ethereum-php copied to clipboard
Unable to use address parameter for ERC20 contracts
Hi,
I'm trying to fetch account balances from ERC20 smart contracts. To do so, I have the ERC20 standard ABI, so I should just have to call the "balanceOf" function of the contracts. According to the ABI, the "balanceOf" function has just one input : the account address.
Here is my piece of code with a specific example where $abi_json
is a json of the ERC20 ABI:
$contract_address = "0x123ab195dd38b1b40510d467a6a359b201af056f";
$account_address = "0xcc7d71df5e7b6c765448fb7ec79a602d6e3ab4f8";
$abi = new Abi(json_decode($abi_json));
$response=$eth->eth_call(new CallTransaction(new EthD20($contract_address),
null, null, null, null,
$abi->encodeFunction("balanceOf",[new EthD20($account_address)])),
new EthBlockParam());
It turns out that the response value is 0, but it should be positive with this particular provided addresses.
I added logs in the Ethereum::request method and I found out that the "data" field sent is :
0x70a08231cc7d71df5e7b6c765448fb7ec79a602d6e3ab4f8
.
The first 8 characters 70a08231
represent the signature of the "BalanceOf" function, and the rest is the address sent as an input, on 40 characters.
But it looks like the Ethereum Node is expecting this address to be padded in a 64 characters string. I could prove that with the geth js console on my Parity node :
> eth.call({to:"0x123ab195dd38b1b40510d467a6a359b201af056f" , data: "0x70a08231cc7d71df5e7b6c765448fb7ec79a602d6e3ab4f8"});
"0x0000000000000000000000000000000000000000000000000000000000000000"
> eth.call({to:"0x123ab195dd38b1b40510d467a6a359b201af056f" , data: "0x70a08231000000000000000000000000cc7d71df5e7b6c765448fb7ec79a602d6e3ab4f8"});
"0x00000000000000000000000000000000000000000000000000000198a3bd5246"
Am I doing something wrong while preparing the "eth_call" request ? How should I do it so that the address is padded to a 64 characters string in the data field ?
Thanks for submitting. I will have a look after Devcon next week. PRs are welcome too.
I met the same question
我遇到了这个问题,返回值为空
Abi.php中45行在签名后面加24个0即可解决这个问题
Would be really helpful id you stick to English.
The encodedFunction does not pad to uint256 (32 bytes) of data. you can add str_pad on the parameters for 64 hex values (32 bytes) with leading zero.
you can update at Abi.php:
/**
* @param $methodName
* @param $values array
*
* @return EthD
* @throws \InvalidArgumentException
* @throws \Exception
*/
public function encodeFunction(string $methodName, array $values)
{
$m = $this->getParamDefinition($methodName);
if (count($m->inputs) !== count($values)) {
throw new \InvalidArgumentException('Expected ' . count($m->inputs) . ' params but got ' . count($values));
}
// [METHOD 4bytes] + [PARAMS]
$params = $this->getSignature($m);
foreach ($values as $i => $val) {
$expectedType = $m->inputs[$i]->type;
$validAbiType = self::convertByAbi($expectedType, $val);
$params .= str_pad(EthereumStatic::removeHexPrefix($validAbiType->encodedHexVal()),64,'0',STR_PAD_LEFT);
}
return new EthD($params);
}