6 min read

🧰 Web3 [Serie Part 6/10] - Send Ether to a Smart Contract

🧰 Web3 [Serie Part 6/10] - Send Ether to a Smart Contract

Introduction

Sometimes it's necessary to load the Smart Contract with Ethers. Thus, we need to be able to send some token to our Smart Contract.

Since we are modifying the Blockchain, it will have to be mined, and by consequence it will cost some gas fees.

Actually, there are two ways to send Ether to a Smart Contract.

Two ways to send Ether to a Smart Contract
Two ways to send Ether to a Smart Contract

Method #1: Execute a Function

We will be using a different Smart Contract code for this new part. Thus, let's create a new file 'MyContract2.sol' in our contracts directory, and copy the code below. Comments are following.

pragma solidity >=0.4.16 <0.9.0;

contract MyContract2 {
    string public message;

    function sendEther() external payable {
        message = 'Ether sent!';
    }

    function() external payable {
        message = 'Fallback function!';
    }
}
MyContract2.sol
  • We define a new contract MyContract2 including 2 functions.
  • We declare a public variable called message as a string type.
  • Function sendEther() is simulating a payment, while the second function is a fallback function. It will be detailed in section.

Don't forget to adapt the migration file (2_contract_deploy.js) accordingly.

const MyContract = artifacts.require('MyContract');
const MyContract2 = artifacts.require('MyContract2');

module.exports = function(deployer){
    deployer.deploy(MyContract);
    deployer.deploy(MyContract2);
}
2_contract_deploy.js

We simply added the MyContract2 to be deployed. If you want things cleaner, you can drop the MyContract since we won't use it anymore. It's up to you.

Now, we can migrate our new MyContract2.sol by running the following command in our terminal:

truffle migrate --reset

Among the results, you should see our MyContract2 deployment feedback:

Deploying 'MyContract2'
   -----------------------
   > transaction hash:    0x21f9754b72d2bfc595bda75c8a3c12e7fc9e0b415bf757c561d86b51d81e845d
   > Blocks: 0            Seconds: 0
   > contract address:    0xE5704600e4f2a0B2b2Fb5F07002F819D0EDC86A4
   > block number:        9
   > block timestamp:     1630438020
   > account:             0x8ba7dDC383130c3D5c3afC76AD3f3343571246E8
   > balance:             99.98120808
   > gas used:            209894 (0x333e6)
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00419788 ETH
MyContract2.sol migration & deployment results

Now, that we deployed our new MyContract2.sol successfully, we can move on our Javascript script. We will create a new index2.js and copy the below code. Comments are following.

const Web3 = require('web3');
const MyContract2 = require('./build/contracts/MyContract2.json');

const main = async() => {
    const web3 = new Web3('http://127.0.0.1:7545');

    const id = await web3.eth.net.getId();
    const contract = new web3.eth.Contract(
        MyContract2.abi,
        MyContract2.networks[id].address
    );

    const accounts = await web3.eth.getAccounts();
}

main();
Initial index2.js

Now, let's change this index2.js script to send 1 ETH to our Smart Contract MyContract2.sol.

const Web3 = require('web3');
const MyContract2 = require('./build/contracts/MyContract2.json');

const main = async() => {
    const web3 = new Web3('http://127.0.0.1:7545');

    const id = await web3.eth.net.getId();
    const contract = new web3.eth.Contract(
        MyContract2.abi,
        MyContract2.networks[id].address
    );

    const accounts = await web3.eth.getAccounts();

    const receipt = await contract.methods.sendEther().send({
        from: accounts[0],
        value: '1000000000000000000'
    });

    console.log(receipt);
    console.log(await contract.methods.message().call());
}

main();
Updated index2.js

Here we call our sendEther() methods, using 'send API'. The send method requires several parameters. We will be using the 2 following parameters (more details here in the doc):

  • From: The address the transaction should be sent from.
  • Value: The value transferred for the transaction in wei.

Note: 1 WEI = 10^(-18) ETH.

🚨 WARNING, there is a caveat here 🚨

  • As you can see, the value we are transferring is written as a String type with quite a lot of 0.
  • If we don’t write the value as above, the value will be in Wei (i.e. 10^-18 ETH). Thus, you should write 1 000 000 000 000 000 000 . The problem is that such big numbers are not managed by Javascript. That’s why the trick is to write it as a String type.
  • If you have to perform math operations on this number, I recommend using the bn.js library. Here we keep it simple, and use the String version.

This being said, let's run our index2.js . We will see the following results:

{
  transactionHash: '0x033bf75f4e6891bdc130dc172ad18f0df9d08ab7675c0d6976f3e0ca21e35a57',
  transactionIndex: 0,
  blockHash: '0x2ac3d17d28f36a594cb778b631efe33f69a08bb88bfefc2e77190ef2cff2f035',
  blockNumber: 11,
  from: '0x8ba7ddc383130c3d5c3afc76ad3f3343571246e8',
  to: '0xe5704600e4f2a0b2b2fb5f07002f819d0edc86a4',
  gasUsed: 42365,
  cumulativeGasUsed: 42365,
  contractAddress: null,
  status: true,
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  events: {}
}
Ether sent!
index2.js outputs

Hurra ! It works. We get the receipt of our transaction, as well as the message ‘Ether sent!’. Thus, we successfully sent 1 ETH to our Smart Contract (MyContract2).

Method #2: Send Ether Directly

The second method consists in sending Ether to our Smart Contract, without calling any function.

Two ways to send Ether to a Smart Contract
Two ways to send Ether to a Smart Contract

In our Smart Contract, if you remember, we added what we call a ‘fallback’ method. This method will be fired by default, if a wrong function name is called in our JS file, or if no function name is used. It serves as a fallback…

Here is the updated index2.js. Comments are following.

const Web3 = require('web3');
const MyContract2 = require('./build/contracts/MyContract2.json');

const main = async() => {
    const web3 = new Web3('http://127.0.0.1:7545');

    const id = await web3.eth.net.getId();
    const contract = new web3.eth.Contract(
        MyContract2.abi,
        MyContract2.networks[id].address
    );

    const accounts = await web3.eth.getAccounts();

    const receipt = await web3.eth.sendTransaction({
        from: accounts[0],
        to: contract.options.address,
        value: '1000000000000000000',
    });

    console.log(receipt);
    console.log(await contract.methods.message().call());
}

main();
Updated index2.js

Instead of calling a method from the Smart Contract, we call directly the sendTransaction method.

Thus we are not referencing a specific method from our Smart Contract. As parameters we are using:

  • From: same as previous.
  • To: the contract address we want to send ETH to: contract.options.address.
  • Value: same as previous.

Our fallback function should be fired. Like the previous test, we are console.logging the receipt, as well as the value of our public message. It should print ‘Fallback function!’.

After running the code, we see the results below:

{
  transactionHash: '0xb5617cef2b868aef7c296d0a6a6141f0b0e73266c328f8371d7ef474107aadda',
  transactionIndex: 0,
  blockHash: '0x42a605890ba8ea0eb1046490ecdd76c4267c8eaff15b400a7fbf06acd1c60605',
  blockNumber: 12,
  from: '0x8ba7ddc383130c3d5c3afc76ad3f3343571246e8',
  to: '0xe5704600e4f2a0b2b2fb5f07002f819d0edc86a4',
  gasUsed: 28100,
  cumulativeGasUsed: 28100,
  contractAddress: null,
  logs: [],
  status: true,
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
}
Fallback function!
index2.js outputs

🎉 🥳 👯‍♂️ 🎈 Congratulations, it works , hurra ! We successfully sent 1 ETH to our Smart Contract using the fallback method.

Send Ether from an Account to another One

In this additional part, we just want to send some Ethers from an account to another one.

Here, we won't use any Smart Contract.

Let's say, we want to send 1 ETH from Ganache's account #1 to the #2.

Before we start, here are the balances of our Ganache's accounts.

Initial Balances on Ganache i.e. Before the transfer
Initial Balances on Ganache i.e. Before the transfer

The code is simple, I'm sure you could to do it by yourself :-). Comments are following.

const Web3 = require('web3');
const MyContract2 = require('./build/contracts/MyContract2.json');

const main = async() => {
    const web3 = new Web3('http://127.0.0.1:7545');

    const id = await web3.eth.net.getId();
    const contract = new web3.eth.Contract(
        MyContract2.abi,
        MyContract2.networks[id].address
    );

    const accounts = await web3.eth.getAccounts();

    const receipt = await web3.eth.sendTransaction({
        from: accounts[0],
        to: accounts[1],
        value: '1000000000000000000',
    });

    console.log(receipt);
}

main();
index2.js - Transfer Ether from Account #1 to Account #2
  • We use the sendTransaction method without mentioning any Smart Contract here, and we give 3 parameters.
  • From: the account from which the Ether will be withdrew.
  • To: the credited account.
  • Value: the amount of WEI we want to transfer. Again, we use the string format otherwise, we will have issue with Javascript (cf. Big Numbers).
  • Remember, 1 WEI = 1*10^(-18) ETH

Here is our console.log receipt:

{
  transactionHash: '0xd4fb774a9dda670d887785adb36f03505e80a6ae45a2f6dc468ebcd9fedca372',
  transactionIndex: 0,
  blockHash: '0xd927a7cd0746670ae94a53c8ca0f6c23fd72d14b50d7ad6ef25b786e9c77befd',
  blockNumber: 1,
  from: '0x65ca5ecfd87faafe35f63244133efe9edf2abf55',
  to: '0x89d48bf3591db71c2ebd7be9ea86ce52442e474c',
  gasUsed: 21000,
  cumulativeGasUsed: 21000,
  contractAddress: null,
  logs: [],
  status: true,
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
}
index2.js outputs

And we can check our accounts balances from Ganache. We can see that 1ETH has been transfered from Account #1 to Account #2 !

Ganache - Accounts Balance post transfer
Ganache - Accounts Balance post transfer

Hurra! It works! We successfully transferred 1 ETH from Account 1 to Account 2.