3
votes

I want to transfer erc20 tokens from one account to another. I know that I can use transfer or transferFrom function of smart contract wrapper class. But in my case, erc20 token transaction is needed to be signed at client side. And there is no way to pass signedTransaction in smart contract wrapper functions. So, how can I sign erc20 token transaction and perform the transaction using web3j in java.

I found this similar problem. But, its code is not written in java. And I don't know how to encode transfer function in ABI. Send ERC20 token with web3

Thanks in advance.

1

1 Answers

3
votes

it's a bit late but maybe will hep someone:

You can try this:

import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Bool;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.Function;
    // create credentials
    String privateKeyHexValue = Numeric.toHexString(privateKey.data());
    Credentials credentials = Credentials.create(privateKeyHexValue);
    
    // get the next available nonce
    EthGetTransactionCount ethGetTransactionCount = web3.ethGetTransactionCount(credentials.getAddress(), DefaultBlockParameterName.LATEST).send();
    BigInteger nonce = ethGetTransactionCount.getTransactionCount();
    
    // Value to transfer (ERC20 token)
    BigInteger balance = Convert.toWei("1", Convert.Unit.ETHER).toBigInteger();
    
    // create transfer function
    Function function = transfer(dstAddress, balance);
    String encodedFunction = FunctionEncoder.encode(function);
    
    // Gas Parameters
    BigInteger gasLimit = BigInteger.valueOf(71000); // you should get this from api
    BigInteger gasPrice = new BigInteger("d693a400", 16); // decimal 3600000000
    
    // create the transaction
    RawTransaction rawTransaction =
            RawTransaction.createTransaction(
                    nonce, gasPrice, gasLimit, < ERC20_CONTRACT_ADDRESS >, encodedFunction);
    
    // sign the transaction
    byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
    String hexValue = Numeric.toHexString(signedMessage);
    
    // Send transaction
    EthSendTransaction ethSendTransaction = web3.ethSendRawTransaction(hexValue).sendAsync().get();
    String transactionHash = ethSendTransaction.getTransactionHash();

and transfer function could be:

        private Function transfer(String to, BigInteger value) {
            return new Function(
                    "transfer",
                    Arrays.asList(new Address(to), new Uint256(value)),
                    Collections.singletonList(new TypeReference<Bool>() {
                    }));
        }