contract CtaskSale {
    using SafeMath for uint256;

    address private _owner;
    CTASK public _token;
    
    address payable public _vault1;
    address payable public _vault2;
    address payable public _vault3;
    address payable public _vault4;
    
    /*stage 0 = deployed, 1 = tier1 in progress, 2 = tier1 finished, 3 = tier2 in progress,
    4 = tier2 finished and funds withdrawn*/
    uint8 public _stage = 0;
    uint256 public _maxAmount = 7 * (1 ether);
    uint256 public _swapRatio1 = 1700;
    uint256 public _swapRatio2 = 1444;
    uint256 public _cap1 = 250 * (1 ether);
    uint256 public _cap2 = 450 * (1 ether);
    uint256 public _amountRaisedTier1 = 0;
    uint256 public _amountRaisedTier2 = 0;
    uint256 public _amountRaised = 0;
    
    /* only informative values, not enforced by the smart contract */
    uint256 public _tier1StartTime = 0;
    uint256 public _tier1EndTime = 0;
    uint256 public _tier2StartTime = 0;
    uint256 public _tier2EndTime = 0;
    
    mapping(address => uint256) public _amounts;
    
    /**
     * @dev Sets the values for {tokenAddress} and {vault1}, {vault2}, {vault3}, {vault4}.
     *
     * After the sale has finished (closeTier2 is called), eth is distributed to the vaults
     * (3x30% + 10%).
     *
     * All five of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (address tokenAddress, address vault1, address vault2, address vault3, address vault4) {
        _owner = msg.sender;
        _token = CTASK(tokenAddress);
        
        _vault1 = payable(vault1);
        _vault2 = payable(vault2);
        _vault3 = payable(vault3);
        _vault4 = payable(vault4);
    }
    
    /**
     * @dev Accepts eth and issues CTASK tokens. Max amount is 10 ETH, and also current
     * tier caps cannot be exceeded. Each tier has its own swap ratio.
     */
    receive() external payable {
        require(msg.value + _amounts[msg.sender] <= _maxAmount && ((_stage == 1  && _amountRaisedTier1 + msg.value <= _cap1) || (_stage == 3  && _amountRaisedTier2 + msg.value <= _cap2)),
            "Msg value needs to be not more than 7 ETH and current tier opened and unfilled");
        
        if(_stage == 1) {
            _amountRaisedTier1 += msg.value;
            _amountRaised += msg.value;
            _amounts[msg.sender] += msg.value;
            _token.transfer(msg.sender, msg.value * _swapRatio1);
        } else if (_stage == 3) {
            _amountRaisedTier2 += msg.value;
            _amountRaised += msg.value;
            _amounts[msg.sender] += msg.value;
            _token.transfer(msg.sender, msg.value * _swapRatio2);
        } else {
            revert();
        }
    }
    
    /**
     * @dev Changes the swap ratio for tier1. Can be called only by the contract owner
     * and it can be done only before the sale has started.
     */
    function changeSwapRatio1(uint256 newSwapRatio) public {
        require(msg.sender == _owner && _stage == 0, "Msg sender needs to be the owner and current stage 0");
        _swapRatio1 = newSwapRatio;
    }
    
    /**
     * @dev Changes the swap ratio for tier2. Can be called only by the contract owner
     * and it can be done only before the sale has started or, after tier1 has ended but
     * before tier2 has started.
     */
    function changeSwapRatio2(uint256 newSwapRatio) public {
        require(msg.sender == _owner && (_stage == 0 || _stage == 2), "Msg sender needs to be the owner and current stage 0 or 2");
        _swapRatio2 = newSwapRatio;
    }
    
    /**
     * @dev Opens the sale. Can be called only by the contract owner.
     */
    function openTier1() public {
        require(msg.sender == _owner && _stage == 0, "Msg sender needs to be the owner and current stage 0");
        _stage = 1;
    }
    
    /**
     * @dev Closes tier1. Can be called only by the contract owner.
     */
    function closeTier1() public {
        require(msg.sender == _owner && _stage == 1, "Msg sender needs to be the owner and current stage 1");
        _stage = 2;
    }
    
    /**
     * @dev Opens tier2. Can be called only by the contract owner.
     */
    function openTier2() public {
        require(msg.sender == _owner && _stage == 2, "Msg sender needs to be the owner and current stage 2");
        _stage = 3;
    }
    
    /**
     * @dev Closes tier2. Can be called only by the contract owner.
     * Funds are distributed to the vaults.
     */
    function closeTier2() public {
        require(msg.sender == _owner && _stage == 3, "Msg sender needs to be the owner and current stage 3");
        
        _stage = 4;
        
        _vault1.transfer(_amountRaised.mul(3)/10);
        _vault2.transfer(_amountRaised.mul(3)/10);
        _vault3.transfer(_amountRaised.mul(3)/10);
        _vault4.transfer(_amountRaised/10);
    }
    
    /**
     * @dev _tier1StartTime setter.
     */
    function setTier1StartTime(uint256 newTime) public {
        require(msg.sender == _owner, "Msg sender needs to be the owner");
        _tier1StartTime = newTime;
    }
    
    /**
     * @dev _tier1EndTime setter.
     */
    function setTier1EndTime(uint256 newTime) public {
        require(msg.sender == _owner, "Msg sender needs to be the owner");
        _tier1EndTime = newTime;
    }
    
        /**
     * @dev _tier2StartTime setter.
     */
    function setTier2StartTime(uint256 newTime) public {
        require(msg.sender == _owner, "Msg sender needs to be the owner");
        _tier2StartTime = newTime;
    }
    
    /**
     * @dev _tier2EndTime setter.
     */
    function setTier2EndTime(uint256 newTime) public {
        require(msg.sender == _owner, "Msg sender needs to be the owner");
        _tier2EndTime = newTime;
    }
    
}
function setTier1EndTime(uint256 newTime) public {
    require(msg.sender == _owner, "Msg sender needs to be the owner");
    _tier1EndTime = newTime;
}

/**
 * @dev _tier1EndTime setter.
 */