Web3 商店

发布: (2026年1月10日 GMT+8 19:41)
3 min read
原文: Dev.to

Source: Dev.to

概览

我编写并部署了一个演示性的 Web3 商店,使用 Solidity 和 ethers.js 进行学习实践。旧书推荐的工具(web3.js、Truffle、Ganache)已经过时,所以我使用了现代化的工具来构建项目。

环境搭建

选择开发框架

在构建和部署智能合约时,我选择了 Forge(Foundry 的一部分)而不是 Hardhat。两者都提供本地测试网络;我使用 Anvil,它是 Forge 的高速内存以太坊节点。

在控制台启动 Anvil;它会自动创建带资金的账户并打印 RPC 端点(例如 http://127.0.0.1:8545),MetaMask 可以直接连接该端点。

智能合约

合约实现了两个函数:

购买商品

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);
}

查看已购买商品

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

部署合约

在测试和编译完成后,使用 Forge 发布合约:

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

该命令会返回已部署合约的地址。

前端集成

商店应用使用 ethers v6 与 MetaMask 和区块链交互。

初始化 Provider 和 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);

加载合约 ABI

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

创建合约实例

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

调用合约函数

购买商品

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

获取已购买商品

const userItems = await contract.getBoughtItems();

部署到真实网络

开发完成后,可使用相同的 Forge 工作流将商店及其合约部署到真实网络,只需相应地更新 RPC URL 和私钥。

感谢阅读!欢迎提供反馈或建议。

项目链接:

Back to Blog

相关文章

阅读更多 »

打破我‘完美’合约的测试

第31天——为什么开发工具比以往任何时候都更重要 第一次测试摧毁了我的“完美”智能合约,并不是黑客,而是我自己的开发环境。我…