You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solidity代币赎回功能技术咨询:含赎回函数代码及逻辑说明

代币回购(Redeem)功能完善指南

你的现有redeem函数已经具备核心逻辑,但在安全性、权限控制和标准兼容性上存在隐患,下面是具体的改进方案和完整实现说明:

现有代码的核心问题

  1. 无权限控制:public修饰符允许任何人调用,恶意用户可随意扣减他人代币余额
  2. 无余额校验:直接修改balances会导致余额负数(Solidity 0.8+虽有溢出检查,但仍需提前校验)
  3. ETH转账不安全:transfer函数仅提供2300gas,若买方是合约且fallback函数需要更多gas,转账会失败
  4. 硬编码参数:625和90%折扣写死在代码里,无法动态调整
  5. 代币转移逻辑不严谨:未遵循ERC20标准的授权/转移流程(如果是ERC20代币)

分场景的完整实现

场景1:买方主动发起赎回(最常用)

买方自行调用函数,退回代币换取ETH,无需传入买方地址:

// 基于OpenZeppelin ERC20实现(推荐)
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract VomoToken is ERC20 {
    address public immutable seller; // 固定卖方地址,部署时指定
    uint256 public rprice; // 兑换比例:1 ETH = rprice 枚代币
    uint256 public redeemDiscount; // 赎回折扣百分比(例:90代表实际到账90%)

    constructor(
        uint256 initialSupply,
        address _seller,
        uint256 _rprice,
        uint256 _redeemDiscount
    ) ERC20("VomoToken", "VOMO") {
        _mint(msg.sender, initialSupply);
        seller = _seller;
        rprice = _rprice;
        redeemDiscount = _redeemDiscount;
    }

    function redeem(uint256 vomoValue) public {
        address buyer = msg.sender;

        // 1. 校验买方代币余额充足
        require(balanceOf(buyer) >= vomoValue, "余额不足");
        // 2. 计算应支付的ETH金额(确保单位转换正确,1 ether = 10^18 wei)
        uint256 ethValue = (vomoValue * 1 ether) / rprice;
        uint256 actualEthValue = (ethValue * redeemDiscount) / 100;
        // 3. 校验卖方ETH余额充足
        require(address(seller).balance >= actualEthValue, "卖方ETH不足");
        // 4. 安全转账ETH给买方(替代transfer,兼容合约账户)
        (bool success, ) = payable(buyer).call{value: actualEthValue}("");
        require(success, "ETH转账失败");
        // 5. 转移代币从买方到卖方(遵循ERC20标准)
        _transfer(buyer, seller, vomoValue);
    }
}

场景2:卖方主动发起回购

卖方主动触发回购,需买方先授权代币转移权限:

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

contract VomoToken is ERC20 {
    address public immutable seller;
    uint256 public rprice;
    uint256 public redeemDiscount;

    constructor(
        uint256 initialSupply,
        address _seller,
        uint256 _rprice,
        uint256 _redeemDiscount
    ) ERC20("VomoToken", "VOMO") {
        _mint(msg.sender, initialSupply);
        seller = _seller;
        rprice = _rprice;
        redeemDiscount = _redeemDiscount;
    }

    // 仅允许卖方调用的权限修饰器
    modifier onlySeller() {
        require(msg.sender == seller, "仅卖方可调用");
        _;
    }

    function redeem(address _buyer, uint256 vomoValue) public onlySeller {
        // 1. 校验买方已授权足够代币给卖方
        require(allowance(_buyer, msg.sender) >= vomoValue, "授权不足");
        // 2. 校验买方代币余额充足
        require(balanceOf(_buyer) >= vomoValue, "余额不足");
        // 3. 计算ETH金额
        uint256 ethValue = (vomoValue * 1 ether) / rprice;
        uint256 actualEthValue = (ethValue * redeemDiscount) / 100;
        // 4. 校验卖方ETH余额充足
        require(address(msg.sender).balance >= actualEthValue, "ETH不足");
        // 5. 安全转账ETH
        (bool success, ) = payable(_buyer).call{value: actualEthValue}("");
        require(success, "转账失败");
        // 6. 从买方转移代币到卖方(基于授权)
        _transfer(_buyer, msg.sender, vomoValue);
    }
}

关键注意事项

  • 权限控制:必须限制调用者范围,避免恶意操作
  • 精度处理:整数除法可能导致精度损失,若需更高精度可使用OpenZeppelin的SafeMath或定点数库
  • 事件监控:ERC20的Transfer事件会自动触发,可用于链上监控回购行为
  • 测试验证:需在测试网验证余额扣减、ETH转账、权限控制等所有逻辑,避免主网损失

内容的提问来源于stack exchange,提问作者Vijay Thakur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 08:15:41