I’m getting error VM Exception while processing transaction: revert SafeERC20: low-level call failed
when trying to run buyTokens function
My code:
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.4.0/contracts/token/ERC20/IERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.4.0/contracts/token/ERC20/SafeERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.4.0/contracts/GSN/Context.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.4.0/contracts/math/SafeMath.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.4.0/contracts/utils/ReentrancyGuard.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.4.0/contracts/ownership/Ownable.sol";
import "./MyToken.sol";
import "./TokenWhitelist.sol";
contract MyCrowdsale is Context, ReentrancyGuard, Ownable {
using SafeMath for uint256;
using SafeERC20 for IERC20;
address payable private _startupAddr;
uint256 private _tokenPrice;
uint256 private _tokensSold;
// Amount of wei raised
uint256 private _weiRaised;
IERC20 private _tokenContract;
TokenWhitelist private _whitelist;
/**
* 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 TokensPurchased(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
constructor(
uint256 rate,
address payable startupAddr,
MyToken token,
TokenWhitelist whitelist_
)
public
{
require(rate > 0, "Crowdsale: rate is 0");
require(address(whitelist_) == 0x80C92cc0b675018ef95b4c000e22C675c3A5a41a, "Crowdsale: wrong whitelist address"); // endereço hardcoded
require(whitelist_.checkWhitelisted(startupAddr), "Crowdsale: wallet is not whitelisted");
require(address(token) != address(0), "Crowdsale: token is the zero address");
_tokenPrice = rate;
_tokenContract = token;
_whitelist = whitelist_;
_startupAddr = startupAddr;
}
function tokenPrice() public view returns (uint256) {
return _tokenPrice;
}
function tokensSold() public view returns (uint256) {
return _tokensSold;
}
function totalTokenSupply() public view returns (uint256){
return _tokenContract.totalSupply();
}
/**
* @return the amount of wei raised.
*/
function weiRaised() public view returns (uint256) {
return _weiRaised;
}
/**
* @dev fallback function ***DO NOT OVERRIDE***
* Note that other contracts will transfer funds with a base gas stipend
* of 2300, which is not enough to call buyTokens. Consider calling
* buyTokens directly when purchasing tokens from a contract.
*/
function () external payable {
buyTokens(_msgSender());
}
/**
* @dev low level token purchase ***DO NOT OVERRIDE***
* This function has a non-reentrancy guard, so it shouldn't be called by
* another `nonReentrant` function.
* @param beneficiary Recipient of the token purchase
*/
function buyTokens(address beneficiary) public nonReentrant 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 TokensPurchased(_msgSender(), beneficiary, weiAmount, tokens);
// _updatePurchasingState(beneficiary, weiAmount);
_forwardFunds();
// _postValidatePurchase(beneficiary, weiAmount);
}
/**
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met.
* Use `super` in contracts that inherit from Crowdsale to extend their validations.
* Example from CappedCrowdsale.sol's _preValidatePurchase method:
* super._preValidatePurchase(beneficiary, weiAmount);
* require(weiRaised().add(weiAmount) <= cap);
* @param beneficiary Address performing the token purchase
* @param weiAmount Value in wei involved in the purchase
*/
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
require(beneficiary != address(0), "Crowdsale: beneficiary is the zero address");
require(weiAmount != 0, "Crowdsale: weiAmount is 0");
require(_whitelist.checkWhitelisted(beneficiary), "Crowdsale: beneficiary is not whitelisted");
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
}
/**
* @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 view {
// solhint-disable-previous-line no-empty-blocks
}
/**
* @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 {
_tokenContract.safeTransfer(beneficiary, tokenAmount);
}
/**
* @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send
* 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 {
// solhint-disable-previous-line no-empty-blocks
}
/**
* @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.div(_tokenPrice);
}
/**
* @dev Determines how ETH is stored/forwarded on purchases.
*/
function _forwardFunds() internal {
_startupAddr.transfer(msg.value);
}
}