Web3 store
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: