智能合约:Solidity(基于以太坊或兼容链,如 Polygon、BSC)(仅供学习区块链知识,不可进行违法开发应用)

开发工具:Hardhat 或 Truffle(编译、部署合约),OpenZeppelin(安全合约模板)

代码实现

1. MUSD 代币合约

基于 ERC-20 标准,使用 OpenZeppelin 模板。

javascript 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MUSD is ERC20 {
    constructor() ERC20("Mall USD", "MUSD") {
        _mint(msg.sender, 1000000 * 10**18); // 初始发行 100万 MUSD
    }

    // 商城合约可以调用此函数铸造更多 MUSD 作为奖励
    function mint(address to, uint256 amount) public {
        _mint(to, amount);
    }
}
2. NFT 商品合约

基于 ERC-721,每个商品是一个独特的 NFT。

javascript 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract ProductNFT is ERC721 {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    mapping(uint256 => string) private _tokenURIs;

    constructor() ERC721("ProductNFT", "PNFT") {}

    function mintNFT(address to, string memory tokenURI) public returns (uint256) {
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
        _mint(to, newItemId);
        _setTokenURI(newItemId, tokenURI);
        return newItemId;
    }

    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal {
        _tokenURIs[tokenId] = _tokenURI;
    }

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        return _tokenURIs[tokenId];
    }
}
3. 商城合约

核心逻辑,处理上架和购买。

javascript 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./ProductNFT.sol";
import "./MUSD.sol";

contract Mall {
    ProductNFT public productNFT;
    IERC20 public usdc; // USDC 合约地址
    MUSD public musd;

    struct Item {
        uint256 tokenId;
        address seller;
        uint256 price; // 以 USDC 为单位
        bool isSold;
    }

    mapping(uint256 => Item) public items;
    uint256 public itemCount;

    event ItemListed(uint256 tokenId, address seller, uint256 price);
    event ItemSold(uint256 tokenId, address buyer, uint256 price);

    constructor(address _productNFT, address _usdc, address _musd) {
        productNFT = ProductNFT(_productNFT);
        usdc = IERC20(_usdc);
        musd = MUSD(_musd);
    }

    // 商家上架商品
    function listItem(string memory tokenURI, uint256 price) external {
        uint256 tokenId = productNFT.mintNFT(address(this), tokenURI);
        itemCount++;
        items[tokenId] = Item(tokenId, msg.sender, price, false);
        emit ItemListed(tokenId, msg.sender, price);
    }

    // 用户用 USDC 购买商品
    function buyItem(uint256 tokenId) external {
        Item storage item = items[tokenId];
        require(!item.isSold, "Item already sold");
        require(usdc.transferFrom(msg.sender, item.seller, item.price), "USDC transfer failed");

        item.isSold = true;
        productNFT.transferFrom(address(this), msg.sender, tokenId);

        // 奖励买家 1 MUSD
        musd.mint(msg.sender, 1 * 10**18);

        emit ItemSold(tokenId, msg.sender, item.price);
    }
}
4. 前端实现(React + Ethers.js)

以下是简化的前端代码,假设已配置好 MetaMask 和合约地址。

javascript 复制代码
import { ethers } from "ethers";
import React, { useState } from "react";
import MallABI from "./abis/Mall.json"; // 商城合约 ABI
import USDCABI from "./abis/USDC.json"; // USDC ABI

const MallDApp = () => {
  const [provider, setProvider] = useState(null);
  const [account, setAccount] = useState(null);

  const mallAddress = "0xYourMallContractAddress";
  const usdcAddress = "0xYourUSDCContractAddress"; // 测试网 USDC 地址

  // 连接钱包
  const connectWallet = async () => {
    const provider = new ethers.BrowserProvider(window.ethereum);
    const accounts = await provider.send("eth_requestAccounts", []);
    setProvider(provider);
    setAccount(accounts[0]);
  };

  // 商家上架商品
  const listItem = async () => {
    const signer = await provider.getSigner();
    const mallContract = new ethers.Contract(mallAddress, MallABI, signer);
    const tokenURI = "ipfs://your-ipfs-hash"; // 商品元数据
    const price = ethers.parseUnits("10", 6); // 假设 10 USDC,6 位小数
    await mallContract.listItem(tokenURI, price);
  };

  // 用户购买商品
  const buyItem = async (tokenId) => {
    const signer = await provider.getSigner();
    const mallContract = new ethers.Contract(mallAddress, MallABI, signer);
    const usdcContract = new ethers.Contract(usdcAddress, USDCABI, signer);

    // 授权 USDC
    const price = items[tokenId].price; // 从状态或合约获取价格
    await usdcContract.approve(mallAddress, price);
    await mallContract.buyItem(tokenId);
  };

  return (
    <div>
      <button onClick={connectWallet}>连接钱包</button>
      <button onClick={listItem}>上架商品</button>
      <button onClick={() => buyItem(1)}>购买商品 (ID: 1)</button>
    </div>
  );
};

export default MallDApp;

部署与测试

  1. 编译与部署
    • 用 Hardhat 编译合约:npx hardhat compile。
    • 部署到测试网:编辑 hardhat.config.js,添加网络配置,然后运行 npx hardhat run scripts/deploy.js --network sepolia。
  2. 测试流程
    • 用 MetaMask 连接测试网,获取测试 USDC(可用 faucet)。
    • 商家调用 listItem,检查 NFT 是否铸造。
    • 用户授权 USDC 并调用 buyItem,验证 NFT 和 USDC 转移。
相关推荐
企业对冲系统官3 小时前
期货套保系统移动端操作的技术架构与实现
算法·架构·区块链·github
TechubNews5 小时前
BEATOZ区块链专业企业与韩国头部旅游集团MODETOUR从签署MOU迈向网络验证节点合作
大数据·人工智能·区块链
数说星榆1811 天前
模型即服务(MaaS)生态的去中心化探索
去中心化·区块链
老蒋每日coding1 天前
区块链技术系列(一)—— 联盟链FISCO BCOS 技术架构
区块链
公链开发2 天前
2026 Web3机构级风口:RWA Tokenization + ZK隐私系统定制开发全解析
人工智能·web3·区块链
ICkaihuuu2 天前
MT4 黄金交易:如何设置与计算交易手数(2026 最新指南)
区块链
数据大魔方2 天前
【期货量化入门】Python获取期货实时行情(TqSdk完整代码)
开发语言·python·区块链
CryptoRzz2 天前
印度股票数据API对接实战(实时行情与IPO功能全解析)
websocket·区块链·github·共识算法·分布式账本
软件工程小施同学2 天前
区块链论文速读 CCF A--TDSC 2025 (3)
运维·服务器·区块链
ATMQuant3 天前
量化指标解码13:WaveTrend波浪趋势 - 震荡行情的超买超卖捕手
人工智能·ai·金融·区块链·量化交易·vnpy