When I use web3js and Truffle, I cannot send tokens to another wallet without the Token Contract ABI. But Metamask only requires the token contract address to recognize and send the ERC20 tokens. How do they do it?
ERC20 Tokens – How Metamask Sends ERC20 Tokens Without ABI
abierc-20metamask
Related Solutions
I assume you are using Web3j and a deployed smart contract implementing ERC20 interface, where transfer method looks like this:
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balances[msg.sender] >= _value && _value > 0);
balances[msg.sender] -= _value;
balances[_to] += _value;
return true;
}
You can use web3j wrapper for your contract to call contract methods on a blockahain. Suppose your Contract filname is MyContract.sol
, then you'll need solc compiler and web3j tool and do the following in your console:
$ solc {contract}.sol --bin --abi --optimize -o {output-dir}/
this will generate .abi
and .bin
files from which you generate a java wrapper class:
$ web3j solidity generate /path/to/<smart-contract>.bin /path/to/<smart-contract>.abi -o /path/to/src/main/java -p com.your.organisation.name
This will produce a java wrapper class for your contract like MyContract.java
on which you can call all the methods available on the smart contract:
import static org.web3j.tx.Contract.GAS_LIMIT;
import static org.web3j.tx.ManagedTransaction.GAS_PRICE;
//web3j initialization code goes here
//Load the deployed contract:
MyContract contract = MyContract.load(contractAddress, web3j, credentials, GAS_PRICE, GAS_LIMIT);
//Call methods on the contract:
Future<> result = contract.transfer(_to, _value);
You can find more info on how to work with smart contracts wrappers here. Hope that helps.
edit.
abi
and bin
for this particular contract can be obtained from etherscan.io
You can transfer tokens even if you are not the owner of the contract. But you are only abe to transfer tokens available to your own account as seen in the contract:
function transfer(address _to, uint256 _amount) returns (bool success) {
if (balances[msg.sender] >= _amount
&& _amount > 0
&& balances[_to] + _amount > balances[_to]) {
balances[msg.sender] -= _amount;
balances[_to] += _amount;
Transfer(msg.sender, _to, _amount);
return true;
} else {
return false;
}
}
Donot use value
field if you dont want to send ether
. Value
field is only used for ether
. Now you have to construct the data
for the transaction. if using web3@0.2.0
then you can do
contractData = contractInstance.transfer.getData(address, amount)
//contractData = '0x12345643213456000000000023434234'
this will give you the data for the transaction. After that the transaction object
will look like this
{
nonce: nonceHex,
gasPrice: gasPriceHex,
gasLimit: gasLimitHex,
data: contractData,
to: contractAddress,
chainId: 1(main net), 2(expanse), 4(rinkeby)
from: fromAddress
}
But it wont say "Pay 100 ABC tokens"
, but there will be a popup for confirmation to send transaction
Best Answer
Metamask uses internally a simple ERC20 compatible ABI, defined on the basis of the standard. As you may know, any
is described by the same ABI element for any possible contract existing incorporating it, being it (the ABI element) nothing more that an hashed description of the call name and of the parameters type.
So if you suppose that the contract to connect with has, at least, one transfer, one balanceOf, one approve, one transferFrom and so on, you can write down a usable ABI that shall give you access to those functions in the contract without hassle.
Of course you shall not be able to access any other function existing in the specific contract that you did not described in advance using that approach.