我的网页上的 Solidity 众筹功能失败,但直接发送时成功,但成功交易时不发送 ERC20

Posted

技术标签:

【中文标题】我的网页上的 Solidity 众筹功能失败,但直接发送时成功,但成功交易时不发送 ERC20【英文标题】:Solidity crowdsale function fails on my web page but is successful when sent directly but doesn't send ERC20 on successful transaction 【发布时间】:2020-10-25 20:04:33 【问题描述】:

我有一个众筹合约,它直接从我的代币合约中的铸币函数接收代币。该函数铸币并将其发送到众筹账户地址。当我跑步时

let token = await Token.deployed()

await token.mint('0xc2646F5bcB2B59a3AB3E6ccD1806D8be241C4A94',50000000000000)

在松露控制台中。我得到一个 tx 哈希和一个传输事件。之后,我向众筹账户进行交易,我测试到众筹地址的交易,它使用 21000 气体

web3.eth.sendTransaction( to: "0x7B012920910A2A29673A15b24335617bbd2CF451", from: accounts[0], value: 2)

它返回一个 tx 哈希并且它可以工作。当我通过 metamask 尝试并将交易发送到众筹时,我将 gaslimit 指定为 200,000,我读到这是众筹合约的推荐金额。我发送了 1 个以太币,它说等待几秒钟,然后说成功。当我点击与众筹合约交互的网页时,交易失败

当我查看 metamask 中的交易详细信息时,它说 6385876 是失败交易的气体限制。我的 Crowdsale 合同如下所示。

pragma solidity ^0.5.0;

import "./SafeMath.sol";
import "./Token.sol";

contract Own 

    address public owner;

    constructor() public 
        owner = msg.sender;
    

    modifier onlyOwner 
        require(msg.sender == owner);
        _;
    



// rate is 1 token = 0.01 ether

contract Crowdsale is Own, Token 
    using SafeMath for uint256;

    constructor() public payable
        rate = 10000000000000000;
        wallet = 0xAa6f0507bF7baaB35E2f0Bb9a318E1D0F61F371b;
    

    Token public token;
    address payable public wallet;
    uint256 public rate;

    event TokenPurchase(address recipient, uint256 numPaid, uint256 numTokensPurchased);

    function buyTokens() public payable 
        // Define a uint256 variable that is equal to the number of wei sent with the message.
        uint256 val = msg.value;
        require(msg.sender != address(0));
        require(val > 0);
        uint256 tokenAmount = _getTokenAmount(val);
        require(token.balanceOf(address(this)) >= tokenAmount);
        token.transferFrom(address(this), msg.sender, tokenAmount);
        emit TokenPurchase( msg.sender, val, tokenAmount);
        _forwardFunds();
    
    
    function () external payable
        buyTokens();
    

    function _getTokenAmount(uint256 weiVal) internal returns (uint256) 
        return weiVal * rate;
    

    function _forwardFunds() internal 
        transferFrom.(address(this), address(wallet), address(this).balance);
    

前端是用react写的。我已经实例化了 web3 对象,就像在另一个成功发送事务的页面中一样。

  const accounts = await MyWeb3.getInstance().getAccounts();
  console.log(accounts);
  const crowdsale = MyWeb3.getInstance().getContract(Crowdsale);
  const crowdsaleInstance = await MyWeb3.getInstance().deployContract(crowdsale);
  console.log(crowdsaleInstance);
  const res = crowdsaleInstance.eth.sendTransaction( to: "0x7B012920910A2A29673A15b24335617bbd2CF451", from: accounts[0], value: ether)//.estimateGas(gas: 200000)

我通过元掩码直接发送到众筹地址而不是在网页上的交易有效,但它们不会将任何 ERC20 代币发送到买家地址。当我将我的自定义令牌添加到元掩码时,它会识别它并制作一个钱包,但余额保持在 0。它应该转发资金,但它也没有这样做。它只是将以太币发送到 Crowdsale 合约地址,资金就留在 ganache 账户的顶部。

这是我项目的最后一部分,我已经被这个问题困扰了 3 天。我想不通。我真的需要帮助来理解问题以及如何解决它。谢谢你

【问题讨论】:

【参考方案1】:

首先,让buyTokens() 函数工作,然后尝试fallback 函数。为此,请检查值:

    msg.value传递require
require(val > 0);
    众筹合约代币余额,通过require
require(token.balanceOf(address(this)) >= tokenAmount);

注意:您可以向require 添加一条消息,以了解它落在哪里。

    最重要的是,以下代码的含义:
function _forwardFunds() internal 
  transferFrom.(address(this), address(wallet), address(this).balance);

也许你需要:

function _forwardFunds() internal 
  wallet.transfer(address(this).balance);

【讨论】:

感谢您的帮助。最后,这是因为迁移文件为众筹提供了与 truffle 输出中不同的地址,但我最终找到了解决方法。谢谢你的回答【参考方案2】:
function _getTokenAmount(uint256 weiVal) internal returns (uint256) 
        return weiVal * rate;
    

不应该

function _getTokenAmount(uint256 weiVal) internal returns (uint256) 
        return weiVal / rate;
    

【讨论】:

以上是关于我的网页上的 Solidity 众筹功能失败,但直接发送时成功,但成功交易时不发送 ERC20的主要内容,如果未能解决你的问题,请参考以下文章

Solidity:关于 ERC20 代币创建和预售(众筹)的问题

第154篇 Solidity 中众筹的实现

第154篇 Solidity 中众筹的实现

Solidity 智能合约开发工具准备第一篇

智能合约学习笔记——solidity语法

solidity基础知识