如何将我方发行的ERC20代币作为产品支付费用,相关智能合约如何实现?
ERC20代币支付商品售卖智能合约实现答疑
一、适配50枚指定ERC20支付规则的智能合约编写方案
你可以基于OpenZeppelin的标准ERC20接口开发售卖合约,核心逻辑包含授权校验、代币划转、权益发放三个环节,参考实现代码如下:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract ProductSales is ReentrancyGuard, Ownable { // 硬编码指定的ERC20代币合约地址,替换为你方发行的代币实际地址 address public constant MY_ERC20_TOKEN = 0xYourERC20ContractAddressHere; // 单份产品支付金额,假设代币小数位为18,50枚即50 * 10**18 uint256 public constant PRICE_PER_PRODUCT = 50 * 10 ** 18; event ProductPurchased(address indexed buyer, uint256 purchaseTime); constructor() Ownable(msg.sender) {} // 消费者调用的购买方法 function purchaseProduct() external nonReentrant { // 校验消费者已经给当前合约授权了足够的代币额度 require(IERC20(MY_ERC20_TOKEN).allowance(msg.sender, address(this)) >= PRICE_PER_PRODUCT, "Insufficient allowance"); // 转移代币到合约所有者(你方收款地址,可自行调整为固定的多签地址等) bool transferSuccess = IERC20(MY_ERC20_TOKEN).transferFrom(msg.sender, owner(), PRICE_PER_PRODUCT); require(transferSuccess, "Token transfer failed"); // 这里补充你方产品发放的逻辑,比如mint对应NFT、记录用户权益等 // _deliverProduct(msg.sender); emit ProductPurchased(msg.sender, block.timestamp); } // 可选:如果需要调整收款地址可以加这个方法,不需要就删掉 function updateRecipient(address newRecipient) external onlyOwner { _transferOwnership(newRecipient); } }
代码说明:
- 你需要提前把
MY_ERC20_TOKEN常量替换为你方实际发行的ERC20代币合约地址,PRICE_PER_PRODUCT要结合你代币的小数位计算,比如你代币小数位是6的话,就写50 * 10 ** 6 - 消费者调用
purchaseProduct方法前,需要先调用你方ERC20代币的approve方法,给当前售卖合约授权至少50枚代币的额度,否则交易会回退 - 你可以在
transferFrom执行成功后,补充你方产品对应的权益发放逻辑,比如发放NFT、记录会员权益等
二、链上逻辑确认支付为指定ERC20代币的方案
核心校验逻辑依赖链上合约地址的唯一性,具体实现方式如下:
- 在售卖合约中将你方ERC20代币的合约地址设置为不可修改的常量,不要提供任何可以修改该地址的公共方法,也不要在购买接口中允许用户传入代币地址参数
- 所有和代币相关的交互(额度查询、转账)都只调用上述常量地址对应的合约,不会和其他任何代币地址产生交互,自然就保证了收到的只能是你指定的代币
- 可选补充校验:部署合约时可以调用该地址的
symbol()、decimals()方法,和你预设的代币参数做比对,避免你自己填错代币地址的低级失误。注意不要用symbol/name作为唯一校验依据,恶意仿冒代币可以伪造相同的名称和符号,只有地址是唯一不可伪造的
内容的提问来源于stack exchange,提问作者Gopal Gurram
相关产品推荐
相关产品推荐

