Search code examples
reactjsethereumsolidityweb3js

Solidity crowdsale function fails on my web page but is successful when sent directly but doesn't send ERC20 on successful transaction


I have a crowdsale contract that receives tokens directly from a mint function in my token contract.the function mints the tokens and sends its to the Crowdsale account address. when I run

let token = await Token.deployed()

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

In the truffle console. I get a tx hash and a transfer event. After that I make a transaction to the crowdsale account I test a transaction to the crowdsale address and it works with 21000 gas

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

it returns a tx hash and it works. when I try it through metamask and send a transaction to the crowdsale I specify the gaslimit at 200,000 which I read was the recommended amount for a crowdsale contract. I send 1 ether and it it says pending for a few seconds and then says success. When I click on the webpage that interacts with the crowdsale contract it fails the transaction with

enter image description here

when I look at the transaction details in metamask it says 6385876 was the gas limit for the failed transactions. My Crowdsale contract looks like the following.

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

the front end is written in react. I have instantiated the web3 object the same way I have in another page that successfully sends transactions.

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

The transactions that I send to the crowdsale address through metamask directly and not on the web page work but they do not send any of the ERC20 tokens to the buyers address. when I add my custom token to metamask it recognizes it and makes a wallet but the balance stays at 0. it is supposed to forward the funds but it doesnt do that either it. it just sends the ether to the Crowdsale contract address and the funds just stay at the top of account in ganache.

This is the last part of my project and I have been stuck on this problem for 3 days. I can't figure this out. I really need help understanding the problem and how to fix it.


Solution

  • First, make the buyTokens() function work, and then try the fallback function. To do this, check the values:

    1. msg.value to pass require:
    require(val > 0);
    
    1. Token balance of the Crowdsale contract, to pass require:
    require(token.balanceOf(address(this)) >= tokenAmount);
    

    NOTE: You can add a message to the require to know where it fell.

    1. And most important, what the following code means:
    function _forwardFunds() internal {
      transferFrom.(address(this), address(wallet), address(this).balance);
    }
    

    Maybe you are required:

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