Web3 store

Published: (January 10, 2026 at 06:41 AM EST)
2 min read
Source: Dev.to

Source: Dev.to

Overview

I wrote and deployed a demo Web3 store using Solidity and ethers.js as a learning exercise. The original tools recommended by an older book (web3.js, Truffle, Ganache) are now obsolete, so I built the project with modern tooling.

Setup

Choosing a Development Framework

For building and deploying smart contracts, I selected Forge (part of Foundry) over Hardhat. Both provide local testnets; I used Anvil, Forge’s fast, in‑memory Ethereum node.

Start Anvil from the console; it automatically creates funded accounts and prints the RPC endpoint (e.g., http://127.0.0.1:8545) that MetaMask can connect to.

Smart Contract

The contract implements two functions:

Purchase an Item

function purchaseItem(uint8 _itemId) external payable {
    uint256 itemCost = 2 gwei; // 0.0012 USD / 0.18 RUB;

    // Forward the funds to the seller
    (bool success, ) = STORE_ADDRESS.call{value: itemCost}("");
    require(success, "Transfer failed");

    boughtItems[msg.sender].push(_itemId);
}

View Purchased Items

function getBoughtItems() external view returns (uint8[] memory) {
    return boughtItems[msg.sender];
}

Deploying the Contract

After testing and compilation, publish the contract with Forge:

forge create ./src/Store.sol:Store \
    --private-key  \
    --rpc-url  \
    --broadcast \
    --constructor-args 

The command returns the deployed contract address.

Frontend Integration

The store application uses ethers v6 to interact with MetaMask and the blockchain.

Initialize Provider and Signer

import { ethers } from "ethers";

const provider = new ethers.BrowserProvider(window.ethereum);
const signerObj = await provider.getSigner();
const balance = await provider.getBalance(signerObj.address);
const balanceFormatted = ethers.formatEther(balance);

Load Contract ABI

import ContractArtifact from "***/Store.json";
const abi = ContractArtifact.abi;

Create Contract Instance

const contract = new ethers.Contract(CONTRACT_ADDRESS, abi, signerObj);

Call Contract Functions

Purchase an Item

contract.purchaseItem(itemId, {
    value: ethers.parseUnits("2", "gwei") // attach the wei
}).then((tx) => tx.wait())
  .then(() => {
      const newItems = items.add(itemId);
      setItems(newItems);
  });

Retrieve Purchased Items

const userItems = await contract.getBoughtItems();

Deployment to Live Network

Once development is complete, the store and its contract can be deployed to a live network using the same Forge workflow, updating the RPC URL and private key accordingly.

Thanks for reading! Any feedback or suggestions are appreciated.

Project link:

Back to Blog

Related posts

Read more »