Buy direct with Crowdsale without using the buyTokens function

First of all, thank the entire community for all the facilities with the standards they share. Thank you very much for saving us so much time.

I have successfully implemented the Crowdsale.sol standard for a token sale. But I would like to use it without using the buytokens function. The idea is that an income is made in the contract, with a fixed amount of weis, and receives the corresponding amount of tokens.

  function buyTokens(address _beneficiary) public payable {

    uint256 weiAmount = msg.value;
    _preValidatePurchase(_beneficiary, weiAmount);

    // calculate token amount to be created
    uint256 tokens = _getTokenAmount(weiAmount);

    // update state
    weiRaised = weiRaised.add(weiAmount);

    _processPurchase(_beneficiary, tokens);
    emit TokenPurchase(
      msg.sender,
      _beneficiary,
      weiAmount,
      tokens
    );

    _updatePurchasingState(_beneficiary, weiAmount);

    _forwardFunds();
    _postValidatePurchase(_beneficiary, weiAmount);
  }

How to make the function execute internally in each entry of weis in the contract, relating the parameter address _beneficiary with the msg.sender?

Another way of saying it is that the contract is listening to activate the shipment if I receive the money.

Thank you

Hey I have done something similar

1 Like

Ops its wonderfull!

I see that you have the minimum purchase but I do not see the maximum purchase that is thehardcap and softcap? True?

It is a very complete contract, it has everything. But, entering weis does not return tokens…

fallback function no works. When send ethers need more gas, thats its ok, but always return a execution reverted…

Does it have to be enabled in some way?

Hey Man, your contract give me "execution reverted" error when I want to deploy it in testserver!

I have made a purchase contract with these characteristics, inheriting from Crowdsale and overwriting the buytokens method.

/SPDX-License-Identifier: Unlicense

pragma solidity ^0.6.12;

import  "./Crowdsale.sol";
import  "./Ownable.sol";
//import  "@openzeppelin/contracts/crowdsale/Crowdsale.sol";
//import  "@openzeppelin/contracts/token/ERC20/Ownable.sol";
//import "hardhat/console.sol";

// trusty contrato de fernando: 0x21176b07a996E62C905e5bf29b1E3e8F1f237d8A

/**
 * Standard de preventa con algunas customizacinones personales.
 *
 *endsold: para la preventa y envia los tokens que no se hayan vendido
 *al propietario
 *TokenBalance: Indica la cantidad de tokens que hay en el contrato
*
 Setrate: Cambia la cantidad de tokens a enviar por 1 BNB cuando queramos.
 *\
 */


interface TokenInterface {
    // determinamos las funciones que necesitamos del ERC20. Tienen que ser iguales.
    function decimals() external view  returns(uint8);
    function balanceOf(address _address) external view returns(uint256);
    function transfer(address _to, uint256 _value) external returns (bool success);
}



contract SALETOKEN is Crowdsale, Ownable {
    
   uint256  public limitBuy = 3000000000000000000;
   
   uint256 public minRate = 100000;
   uint256 public maxRate = 220000;
    
     TokenInterface TokenContract; // interface para manipular metodos del token.

    // tanto _token como _addresstoken son la misma direccion. La diferencia esta en su uso.
    // Debemos pasarlo como contrato y como direccion para 
    // hacer operaciones diferentes.
    constructor  (uint256 _rate, 
    address payable _wallet, 
    BEP20 _token,
    address _addressToken
    ) 
    

        
    Crowdsale(_rate,  _wallet, _token) 
    
    public {
        
        require(_rate >= minRate && _rate <= maxRate , "La cantidad de tokens tiene que estar entre 100000 y 220000");
        
        // pásamos el contrato del token, como direccion para ser usada por la interface
        TokenContract = TokenInterface(_addressToken);
        
        //console.log("Desplegado contrato de venta de los tokens del contrato: ", _token);
        
        
    }
    
     // Funcion que liquida el contrato para que no se pueda vender mas.
    function endSold() public  onlyOwner() {
        
        // compensacion de saldos. 
        require(TokenContract.transfer(owner(), TokenContract.balanceOf(address(this))));
        msg.sender.transfer(address(this).balance);
        weiRaised = 0;
       
    }
    
       function TokenBalance() public view returns (uint256)  {
    return TokenContract.balanceOf(address(this));
    
  }
  
     function setRate(uint256 _newrate) public onlyOwner() {
         
    require(_newrate >= minRate && _newrate <= maxRate , "La cantidad de tokens tiene que estar entre 100000 y 220000");
    rate = _newrate;
  }
  
      function setLimitBuy(uint256 _newLimit) public onlyOwner() {
    limitBuy = _newLimit;
  }
  
      function setLimirates(uint256 _newLimitminRate, uint256 _newLimitmaxRate) public onlyOwner() {
    minRate = _newLimitminRate;
    maxRate = _newLimitmaxRate;
  }
  
   /**
   * @dev low level token purchase ***DO NOT OVERRIDE***
   * @param _beneficiary Address performing the token purchase
   */
  function buyTokens(address _beneficiary) public override payable {
      
    require(TokenContract.balanceOf(_beneficiary) <= limitBuy.mul(rate), "Esta cuenta ya tiene el limite de tokens permitido para la preventa");

    uint256 weiAmount = msg.value;
    
    require(weiAmount <= limitBuy, "Compra excede el máximo de BNBs permitido");
    
    _preValidatePurchase(_beneficiary, weiAmount);

    // calculate token amount to be created
    uint256 tokens = _getTokenAmount(weiAmount);

    // update state
    weiRaised = weiRaised.add(weiAmount);

    _processPurchase(_beneficiary, tokens);
    emit TokenPurchase(
      msg.sender,
      _beneficiary,
      weiAmount,
      tokens
    );
    
  }

}


But I'm still waiting for someone to explain to me why the receive function doesn't work. It works perfectly with its corresponding frontend.

receive function? Do you mean the function buyTokens()

No @Skyge ,
I mean that it works that:

   receive ()  external payable {
    buyTokens(msg.sender);
  }

is within the crowdsale contract:.

What is the source code of the Crowdsale contract, I did not find a suitable contract in the OpenZeppelin repo, in the branch named release-v2.5.0, the compiler version of the contract is 0.5.x

Right now I share it with you


//SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.12;

import  "./BEP20.sol";
import "./SafeMath.sol";


/**
 * @title Crowdsale
 * @dev Crowdsale is a base contract for managing a token crowdsale,
 * allowing investors to purchase tokens with ether. This contract implements
 * such functionality in its most fundamental form and can be extended to provide additional
 * functionality and/or custom behavior.
 * The external interface represents the basic interface for purchasing tokens, and conform
 * the base architecture for crowdsales. They are *not* intended to be modified / overriden.
 * The internal interface conforms the extensible and modifiable surface of crowdsales. Override
 * the methods to add functionality. Consider using 'super' where appropiate to concatenate
 * behavior.
 */
contract Crowdsale  {
  using SafeMath for uint256;

  // The token being sold
  BEP20 public token;

  // Address where funds are collected
  address payable public wallet;

  // How many token units a buyer gets per wei
  uint256 public rate;

  // Amount of wei raised
  uint256 public weiRaised;

  /**
   * Event for token purchase logging
   * @param purchaser who paid for the tokens
   * @param beneficiary who got the tokens
   * @param value weis paid for purchase
   * @param amount amount of tokens purchased
   */
  event TokenPurchase(
    address indexed purchaser,
    address indexed beneficiary,
    uint256 value,
    uint256 amount
  );

  /**
   * @param _rate Number of token units a buyer gets per wei
   * @param _wallet Address where collected funds will be forwarded to
   * @param _token Address of the token being sold
   */
  constructor(uint256 _rate, address payable _wallet, BEP20 _token) public {
    require(_rate > 0);
    require(_wallet != address(0));
//    require(_token != address(0));

    rate = _rate;
    wallet = _wallet;
    token = _token;
  }

  // -----------------------------------------
  // Crowdsale external interface
  // -----------------------------------------

  /**
   * @dev fallback function ***DO NOT OVERRIDE***
   */
  fallback ()  external payable {
    buyTokens(msg.sender);
  }
  
    receive ()  external payable {
    buyTokens(msg.sender);
  }

  /**
   * @dev low level token purchase ***DO NOT OVERRIDE***
   * @param _beneficiary Address performing the token purchase
   */
  function buyTokens(address _beneficiary) public virtual payable {

    uint256 weiAmount = msg.value;
    _preValidatePurchase(_beneficiary, weiAmount);

    // calculate token amount to be created
    uint256 tokens = _getTokenAmount(weiAmount);

    // update state
    weiRaised = weiRaised.add(weiAmount);

    _processPurchase(_beneficiary, tokens);
    emit TokenPurchase(
      msg.sender,
      _beneficiary,
      weiAmount,
      tokens
    );

    _updatePurchasingState(_beneficiary, weiAmount);

    _forwardFunds();
    _postValidatePurchase(_beneficiary, weiAmount);
  }

  // -----------------------------------------
  // Internal interface (extensible)
  // -----------------------------------------

  /**
   * @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations.
   * @param _beneficiary Address performing the token purchase
   * @param _weiAmount Value in wei involved in the purchase
   */
  function _preValidatePurchase(
    address _beneficiary,
    uint256 _weiAmount
  )
   pure internal
  {
    require(_beneficiary != address(0));
    require(_weiAmount != 0);
  }

  /**
   * @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met.
   * @param _beneficiary Address performing the token purchase
   * @param _weiAmount Value in wei involved in the purchase
   */
  function _postValidatePurchase(
    address _beneficiary,
    uint256 _weiAmount
  )
    internal
  {
    // optional override
  }

  /**
   * @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
   * @param _beneficiary Address performing the token purchase
   * @param _tokenAmount Number of tokens to be emitted
   */
  function _deliverTokens(
    address _beneficiary,
    uint256 _tokenAmount
  )
    internal
  {
    token.transfer(_beneficiary, _tokenAmount);
  }

  /**
   * @dev Executed when a purchase has been validated and is ready to be executed. Not necessarily emits/sends tokens.
   * @param _beneficiary Address receiving the tokens
   * @param _tokenAmount Number of tokens to be purchased
   */
  function _processPurchase(
    address _beneficiary,
    uint256 _tokenAmount
  )
    internal
  {
    _deliverTokens(_beneficiary, _tokenAmount);
  }

  /**
   * @dev Override for extensions that require an internal state to check for validity (current user contributions, etc.)
   * @param _beneficiary Address receiving the tokens
   * @param _weiAmount Value in wei involved in the purchase
   */
  function _updatePurchasingState(
    address _beneficiary,
    uint256 _weiAmount
  )
    internal
  {
    // optional override
  }

  /**
   * @dev Override to extend the way in which ether is converted to tokens.
   * @param _weiAmount Value in wei to be converted into tokens
   * @return Number of tokens that can be purchased with the specified _weiAmount
   */
  function _getTokenAmount(uint256 _weiAmount)
    internal view returns (uint256)
  {
    return _weiAmount.mul(rate);
  }

  /**
   * @dev Determines how ETH is stored/forwarded on purchases.
   */
  function _forwardFunds() internal {
    wallet.transfer(msg.value);
  }
}


I have to say that I introduced the receive function by recommendation of remix. In the original contract there is only the fallback

Really a little difficult to get your full code to have a test!

I have deployed contracts like followings and had a try, all worked well:

Rate = 200000, so when use 20 * 10^9 wei to buy crowdsale token, the amount I can get is: 20 * 10^9 * rate = 4*10**15=0.004DAI

And I think you can have a look at this tutorial to learn:

First of all, thank you for your effort in trying to help me.

But the contract works perfectly for me. Except for the aforementioned function.

If you tell me what error you have, maybe I can help you so that you can help me.

Note that the constructor has to enter TWO TIMES the token contract.
One argument is to be used by Crowdsale, and the other is to be used as an interface.

 constructor  (uint256 _rate, 
    address payable _wallet, 
    BEP20 _token,
    address _addressToken
    ) 
    

        
    Crowdsale(_rate,  _wallet, _token) 
    
    public {
        
        require(_rate >= minRate && _rate <= maxRate , "La cantidad de tokens tiene que estar entre 100000 y 220000");
        
        // pásamos el contrato del token, como direccion para ser usada por la interface
        TokenContract = TokenInterface(_addressToken);
        
        //console.log("Desplegado contrato de venta de los tokens del contrato: ", _token);
        
        
    }

So is the current problem you can not buy token by calling receive()?

The rate calculates the amount of tokens that will be received for each ETH or BNB.

In this function from the Standard contract Crowdsale:

  */
  function _getTokenAmount(uint256 _weiAmount)
    internal view returns (uint256)
  {
    return _weiAmount.mul(rate);
  }

Exactly, that's the only problem. It is not necessary because we have built a DAPP but I would like to know why it does not work. should, not?

But it works for me. Here were transaction:

What!!
Have you achieved it by sending the money directly?

Well, I don't know why I can't. I am quite upset...

... any idea, limit gas may be?

Thank you very much for your help..

Yes!! that was the problem...

We need almost 300000 of limit gas...

It is very expensive right?

Sorry, I am not sure.

But just like above, I only use 73k gas.