contract CappedPresale is Presale {
    using SafeMath for uint256;

    event LogMaxCapChanged(address indexed caller, uint256 indexed maxCap);

    // Maximum cap in wei
    uint256 public maxCap;

    constructor(
        uint256 _startBlock,
        uint256 _endBlock,
        uint256 _minDeposit,
        address _wallet,
        address _providerWallet,
        uint256 _maxWhitelistLength,
        uint256 _whitelistThreshold,
        uint256 _feeThreshold1,
        uint256 _feeThreshold2,
        uint256 _lowFeePercentage,
        uint256 _mediumFeePercentage,
        uint256 _highFeePercentage,
        uint256 _maxCap
    )
    Presale(
        _startBlock,
        _endBlock,
        _minDeposit,
        _wallet,
        _providerWallet,
        _maxWhitelistLength,
        _whitelistThreshold,
        _feeThreshold1,
        _feeThreshold2,
        _lowFeePercentage,
        _mediumFeePercentage,
        _highFeePercentage
    )
    public
    {
        require(_maxCap > 0, "_maxCap is zero");
        require(_maxCap >= _feeThreshold2, "_maxCap is lower than _feeThreshold2");
        
        maxCap = _maxCap;
    }

    /**
     * Change the maximum cap of the presale. New value shall be greater than previous one.
     * @param _maxCap The maximum cap of the presale, expressed in wei
     */
    function setMaxCap(uint256 _maxCap) external onlyOwner {
        require(_maxCap > maxCap, "_maxCap is not greater than current maxCap");
        require(!hasEnded(), "presale has ended");
        
        maxCap = _maxCap;

        emit LogMaxCapChanged(msg.sender, _maxCap);
    }

    // overriding Presale#hasEnded to add cap logic
    // @return true if presale event has ended
    function hasEnded() public view returns (bool ended) {
        bool capReached = raisedFunds >= maxCap;
        
        return super.hasEnded() || capReached;
    }

    // overriding Presale#isValidInvestment to add extra cap logic
    // @return true if beneficiary can buy at the moment
    function isValidInvestment(address _beneficiary, uint256 _amount) public view returns (bool isValid) {
        bool withinCap = raisedFunds.add(_amount) <= maxCap;

        return super.isValidInvestment(_beneficiary, _amount) && withinCap;
    }
}
/**
 * @title CappedPresale
 * @dev Extension of Presale with a max amount of funds raised
 */
function hasEnded() public view returns (bool ended) {
    bool capReached = raisedFunds >= maxCap;
        
    return super.hasEnded() || capReached;
}

// overriding Presale#hasEnded to add cap logic
// @return true if presale event has ended