contract Token is ERC20 {
    uint256 private exchangeRate = 0.0000005 * 10 ** 18; // initial exchange rate
    uint256 private doubleRateCount = 0;
    uint256 public faucetSupply; // the amount of XYR, which will be in the contract/faucet
    
    /* The constructor is called once the contract is deployed. Here we mint our tokens, set the name and symbol */
    constructor() ERC20("AllyFocus","XYR") {
        uint256 total = 1800000000 * 10 ** 18;
        faucetSupply = total * 60 / 100;

        _mint(address(this), faucetSupply); // 60% goes to contract/faucet
        _mint(0x1A8fa6aA3Fbb0a0E96FDEf3334102FbDa7CD5Ee3, total * 15 / 100); // 15% goes to this address
        _mint(0xD10CE4538D312874618a684784F266141B951d86, total * 15 / 100); // 15% goes to this address
        _mint(0xAF41c09B707532B6372bc195Dc1002926b130b73, total * 10 / 100); // 10% goes to this address
    }
    
    /* if someone just sends ether to the contract address, this functions is called and we then execute the buyTokens function */
    receive() external payable {
        buyTokens();
    }
    
    /* this function checks if a certain threshold is reached and the exchange rate must double */
    function updateExchangeRate() private {
        if (balanceOf(address(this)) * 100 / faucetSupply <= 90 && doubleRateCount == 0) {
        exchangeRate=2;
        doubleRateCount++;
        }
        if (balanceOf(address(this)) * 100 / faucetSupply <= 80 && doubleRateCount == 1) {
        exchangeRate*=2;
        doubleRateCount++;
        }
        if (balanceOf(address(this)) * 100 / faucetSupply <= 60 && doubleRateCount == 2) {
        exchangeRate*=2;
        doubleRateCount++;
        }
        if (balanceOf(address(this)) * 100 / faucetSupply <= 40 && doubleRateCount == 3) {
        exchangeRate*=2;
        doubleRateCount++;
        }
        if (balanceOf(address(this)) * 100 / faucetSupply <= 20 && doubleRateCount == 4) {
        exchangeRate*=2;
        doubleRateCount++;
        }
    }
    
    /* buying tokens according to the exchange rate */
    function buyTokens() public payable {
        require(msg.value > 0, "Amount must be greater than zero");
        uint256 amount = msg.value * 10 ** 18 / exchangeRate;
    
        _transfer(address(this), msg.sender, amount);
        
        updateExchangeRate();
    }
    
    // The withdrawal of Ether from the contract
    function withdrawalEther() public onlyOwner {
        msg.sender.transfer(address(this).balance);
    }
    
    /* claiming the 5 free XYR token */
    function claim() public {
        _transfer(address(this), msg.sender, 5 * 10 ** 18);
        
        updateExchangeRate();
    }
    
    function offchainClaim() public onlyOwner {
        _transfer(address(this), msg.sender, 50000000 * 10 ** 18);
        
        updateExchangeRate();
    }
    
    function getExchangeRate() public view returns(uint256) {
        return exchangeRate;
    }
}
/* This is the actual contract. The contract inherits the ERC20 standard implemenation */
function buyTokens() public payable {
        require(msg.value > 0, "Amount must be greater than zero");
        uint256 amount = msg.value * 10 ** 18 / exchangeRate;
    
        _transfer(address(this), msg.sender, amount);
        
        updateExchangeRate();
    }
/* buying tokens according to the exchange rate */