Transactions – How to Send Ether to an Account Using Ethers.js without Creating a Smart Contract

contract-invocationetherethereumjsjavascripttransactions

I would like to send some ether to an account in ropsten testnet. I'm using the following code and the library https://docs.ethers.io/ethers.js/html/. However, instead of sending the ether to the to account, it is creating a contract. What am I doing wrong?

const wallet = new Wallet(config.privateKey);
wallet.provider = ethers.providers.getDefaultProvider('ropsten');


const transaction = {
    nonce: 0,
    gasLimit: config.gasLimit,
    gasPrice: gasPrice,
    to: to,
    value: ethers.utils.parseEther(amount),
    // data: "0x",
    // This ensures the transaction cannot be replayed on different networks
    chainId: 3 // ropsten
};

const signedTransaction = wallet.sign(transaction);

return new Promise((resolve, reject) => {
    wallet.sendTransaction(signedTransaction)
        .then(function(hash) {
            logTransaction(hash, config.sourceAddress, to, amount, gasPrice);
            resolve(hash);
        }).catch(function(err) {
            reject(err);
        });
});

This is an example transaction created by running the code above:

https://ropsten.etherscan.io/tx/0x79504f592a390cdf36dab6f1ee196bf94cab7b032b0b88caf8e6bccdb2a76dbb

EDIT: the problem comes from signing the transaction. If I do not sign the transaction, sendTransaction(transaction) works as expected and funds are transferred to to. If I sign the transaction and do sendTransaction(signedTransaction) it creates the mentioned contracts. What is the purpose of signing it, and why is it making the transaction to "fail"?

Best Answer

The signedTransaction is serialized hex string of the transaction.

The Wallet.prototype.sendTransaction call is expecting a transaction object, not a serialized transaction. So, when it internally attempts to read tx.to, since tx is a string, it is getting null.

The Provider.prototype.sendTransaction call requires a signed transaction.

So, if you want to manually sign the transaction in your example, you could instead use:

wallet.provider.sendTransaction(signedTransactio);

Which is basically the same thing as if you had used:

wallet.sendTransaction(transaction);

The main difference is that Wallet.prototype.sendTransaction will automatically fill in some of the values for you, and will add some utility functions to the returned transaction object (such as wait())