all files / contracts/ CrowdSale.sol

0% Statements 0/26
0% Branches 0/48
0% Functions 0/14
0% Lines 0/35
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147                                                                                                                                                                                                                                                                                                     
// SPDX-License-Identifier: MIT
 
pragma solidity ^0.8.9;
 
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
 
contract CrowdSale is Ownable, Pausable, ReentrancyGuard {
    using SafeMath for uint256;
    using Address for address;
 
    // the token to be sold
    IERC20 public _tokenContract;
 
    // number of tokens already sold
    uint256 public _tokensSold;
 
    // the time the campaign will start
    uint public _openingTime;
 
    // the time the campaign will end
    uint public _closingTime;
 
    // the rate conversion between bnb and the token
    uint256 public _rate;
 
    constructor() {}
 
    function setTokenToSell(address tokenContractAddress) public onlyOwner {
        _tokenContract = IERC20(tokenContractAddress);
        emit SetTokenToSell(tokenContractAddress);
    }
    event SetTokenToSell(address tokenContractAddress);
 
    // ref https://docs.openzeppelin.com/contracts/2.x/crowdsales
    // rate: how much tokens each eth will give
    // supply: the ammout of tokens available in this campaign
    // closingTime: the time the campaign will end
    // openingTime: the time the campaign will start
    function configure(uint256 rate, uint openingTime, uint closingTime) public onlyOwner {
        require(openingTime < closingTime, "openingTime must be lower than closingTime");
 
        _rate = rate;
        _openingTime = openingTime;
        _closingTime = closingTime;
        _tokensSold = 0;
        emit  Configure(rate, openingTime, closingTime);
    }
    event Configure(uint256 rate, uint openingTime, uint closingTime);
 
    function configureDates( uint openingTime, uint closingTime) public onlyOwner {
        require(openingTime < closingTime, "openingTime must be lower than closingTime");
        _openingTime = openingTime;
        _closingTime = closingTime;
        emit ConfigureDates(openingTime, closingTime);
    }
    event ConfigureDates( uint openingTime, uint closingTime);
 
    function configureRate( uint256 rate ) public onlyOwner {
        _rate = rate;
        emit ConfigureRate(rate);
    }
    event ConfigureRate( uint256 rate );
 
    // how many tokens you will receive for the amount of bnbs
    function bnb2token(uint256 units) public view returns (uint256){
        return units.mul(_rate).div(10**18);
    }
 
    function buyTokens() public payable whenNotPaused {
        require(block.timestamp <= _closingTime, "Sale has finished");
        require(_openingTime <= block.timestamp, "Sale has not started yet");
        require(msg.value > 0, "You should send money in order to buy tokens");
        uint256 numberOfTokens = bnb2token(msg.value);
 
        require(supply() >= numberOfTokens, "Contract does not have enough tokens");
 
        require(_tokenContract.transfer(msg.sender, numberOfTokens), "Some problem with token transfer");
 
        _tokensSold += numberOfTokens;
 
        emit Sell(msg.sender, numberOfTokens);
    }
    event Sell(address _buyer, uint256 _amount);
 
    function withdrawBNB(address to, uint256 amount) onlyOwner nonReentrant() public {
        uint256 balance = address(this).balance;
        require(amount<=balance,"Amount greater than the balance");
        Address.sendValue(payable(to), amount);
    }
 
    /**
     * @dev Withdraw any ERC20 token from this contract
     * @param tokenAddress ERC20 token to withdraw
     * @param to receiver address
     * @param amount amount to withdraw
     */
    function withdrawERC20(
        address tokenAddress,
        address to,
        uint256 amount
    ) external virtual nonReentrant() onlyOwner {
        require(tokenAddress.isContract(), "ERC20 token address must be a contract");
 
        IERC20 tokenContract = IERC20(tokenAddress);
        require(
            tokenContract.balanceOf(address(this)) >= amount,
            "You are trying to withdraw more funds than available"
        );
 
        require(tokenContract.transfer(to, amount), "Fail on transfer");
    }
 
    function totalBalance() external view returns(uint256) {
        return payable(address(this)).balance;
    }
 
    function supply() public view returns (uint256) {
        return _tokenContract.balanceOf(address(this));
    }
 
//    function endSale() public onlyOwner {
//        require(
//            _tokenContract.transfer(owner(), _tokenContract.balanceOf(address(this))),
//            "Unable to transfer tokens to admin"
//        );
//        // destroy contract and send ethers to the owner
//        // https://solidity-by-example.org/hacks/self-destruct/
////        selfdestruct(payable(owner()));
//    }
 
    function pause() public onlyOwner whenNotPaused {
        _pause();
    }
 
    function unPause() public onlyOwner whenPaused {
        _unpause();
    }
 
    function isPaused() public view returns (bool) {
        return paused();
    }
}