Deploying and Interacting with Smart Contracts Using Web3.js

·

Smart contracts are self-executing programs that run on blockchain networks like Ethereum, enabling trustless automation of agreements and processes. In this comprehensive guide, you'll learn how to deploy and interact with smart contracts using Web3.js, one of the most widely used JavaScript libraries for Ethereum development.

We’ll walk through each step—from writing Solidity code to deploying your contract on a local development network and interacting with it programmatically. Whether you're building decentralized applications (dApps) or exploring blockchain development, mastering these fundamentals is essential.


Prerequisites for Smart Contract Development

Before diving into deployment, ensure your environment supports modern web3 development:

You can verify your setup by running:

node -v
npm -v

These should return version numbers, confirming that both tools are correctly installed.


Setting Up Your Project Environment

Start by creating a dedicated project directory:

mkdir smart-contract-tutorial
cd smart-contract-tutorial

Initialize a new Node.js project:

npm init -y

This generates a package.json file, which will manage your dependencies throughout the project.

👉 Learn how to securely manage blockchain interactions in real-world dApps.


Writing Your First Smart Contract in Solidity

Solidity is the most popular language for writing Ethereum smart contracts. Let’s create a simple contract that stores and updates a number.

Create a file named MyContract.sol and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract MyContract {
    uint256 public myNumber;

    constructor(uint256 _myNumber) {
        myNumber = _myNumber;
    }

    function setMyNumber(uint256 _myNumber) public {
        myNumber = _myNumber;
    }
}

This contract defines:

The public keyword automatically generates a getter function, allowing external access to myNumber.


Compiling the Contract: Generating ABI and Bytecode

To deploy a smart contract, you need two outputs from the compiler:

Install the Solidity compiler via npm:

npm install solc

Then, create a compile.js script:

const solc = require('solc');
const path = require('path');
const fs = require('fs');

const contractName = 'MyContract';
const fileName = `${contractName}.sol`;

const contractPath = path.join(__dirname, fileName);
const sourceCode = fs.readFileSync(contractPath, 'utf8');

const input = {
  language: 'Solidity',
  sources: {
    [fileName]: { content: sourceCode },
  },
  settings: {
    outputSelection: {
      '*': { '*': ['*'] },
    },
  },
};

const compiledCode = JSON.parse(solc.compile(JSON.stringify(input)));
const bytecode = compiledCode.contracts[fileName][contractName].evm.bytecode.object;
const abi = compiledCode.contracts[fileName][contractName].abi;

fs.writeFileSync(path.join(__dirname, 'MyContractBytecode.bin'), bytecode);
fs.writeFileSync(path.join(__dirname, 'MyContractAbi.json'), JSON.stringify(abi, null, '\t'));

console.log('Contract ABI:\n', abi);
console.log('Contract Bytecode:\n', bytecode);

Run the script:

node compile.js

You’ll see two new files: MyContractAbi.json and MyContractBytecode.bin.


Configuring Web3.js and Hardhat Development Network

Now set up the development environment using Hardhat, a powerful Ethereum development tool.

Install Hardhat and Web3.js:

npm install --save-dev hardhat
npm install web3

Initialize Hardhat:

npx hardhat

Select default options. Then start the local network:

npx hardhat node

This launches a local blockchain with pre-funded test accounts at http://127.0.0.1:8545.

In a new terminal, create index.js to test connectivity:

const { Web3 } = require('web3');
const web3 = new Web3('http://127.0.0.1:8545/');

web3.eth.getChainId()
  .then(id => console.log('Connected to Chain ID:', id))
  .catch(console.error);

Run it with:

node index.js

A successful connection confirms your environment is ready.

👉 Discover advanced tools for testing and deploying contracts securely.


Deploying the Smart Contract with Web3.js

Create deploy.js to deploy your contract:

const { Web3 } = require('web3');
const fs = require('fs');
const path = require('path');

const web3 = new Web3('http://127.0.0.1:8545/');
const bytecode = fs.readFileSync(path.join(__dirname, 'MyContractBytecode.bin'), 'utf8');
const abi = require('./MyContractAbi.json');

const myContract = new web3.eth.Contract(abi);
myContract.handleRevert = true;

async function deploy() {
  const accounts = await web3.eth.getAccounts();
  const deployer = accounts[0];

  console.log('Deploying from account:', deployer);

  const deployTx = myContract.deploy({
    data: '0x' + bytecode,
    arguments: [1]
  });

  const gas = await deployTx.estimateGas({ from: deployer });
  console.log('Estimated gas:', gas);

  try {
    const receipt = await deployTx.send({
      from: deployer,
      gas,
      gasPrice: '10000000000'
    });

    console.log('Contract deployed at:', receipt.options.address);
    fs.writeFileSync('MyContractAddress.txt', receipt.options.address);
  } catch (error) {
    console.error('Deployment failed:', error);
  }
}

deploy();

Run:

node deploy.js

On success, you’ll get a contract address saved in MyContractAddress.txt.


Interacting with the Deployed Smart Contract

Now use Web3.js to read and modify data on-chain.

Create interact.js:

const { Web3 } = require('web3');
const fs = require('fs');
const path = require('path');

const web3 = new Web3('http://127.0.0.1:8545/');
const address = fs.readFileSync(path.join(__dirname, 'MyContractAddress.txt'), 'utf8');
const abi = require('./MyContractAbi.json');

const contract = new web3.eth.Contract(abi, address);
contract.handleRevert = true;

async function interact() {
  const account = (await web3.eth.getAccounts())[0];

  // Read current value
  let value = await contract.methods.myNumber().call();
  console.log('Current value:', value.toString());

  // Update value
  const receipt = await contract.methods.setMyNumber(Number(value) + 1).send({
    from: account,
    gas: 100000,
    gasPrice: '10000000000'
  });

  console.log('Transaction hash:', receipt.transactionHash);

  // Read updated value
  value = await contract.methods.myNumber().call();
  console.log('Updated value:', value.toString());
}

interact();

Execute:

node interact.js

You’ll see output like:

Current value: 1
Transaction hash: 0x...
Updated value: 2

Frequently Asked Questions

Q: What is an ABI in smart contracts?
A: The ABI (Application Binary Interface) is a JSON description of a contract’s functions and events. It allows Web3.js to encode and decode data when calling contract methods.

Q: Why do I need bytecode to deploy a contract?
A: Bytecode is the compiled version of your Solidity code that the Ethereum Virtual Machine (EVM) executes. Without it, the network cannot run your logic.

Q: Can I deploy to mainnet using this method?
A: Yes—just change the provider URL and use a wallet with real ETH. Always test on testnets first.

Q: What is gas estimation and why is it important?
A: Gas estimation predicts how much computational effort a transaction requires. Accurate estimates prevent failed transactions due to insufficient gas.

Q: Is Web3.js still relevant with newer alternatives?
A: Absolutely. While libraries like Ethers.js are growing in popularity, Web3.js remains widely used, well-documented, and ideal for Node.js environments.

👉 Access real-time blockchain data and build powerful dApps today.


Core Keywords


By following this guide, you’ve gained hands-on experience in writing, compiling, deploying, and interacting with smart contracts using industry-standard tools. This foundation empowers you to build full-featured decentralized applications on Ethereum.

Remember to always test thoroughly on development networks before going live—and keep learning as the ecosystem evolves.