contract xProjectCrowdsale is Ownable, AllowanceCrowdsale, TimedCrowdsale, CappedCrowdsale, IndividuallyCappedCrowdsale, FinalizableCrowdsale, PostDeliveryCrowdsale {
    using SafeMath for uint256;

    // -- State --

    // Account Contributions
    mapping(address => uint256) private _contributions; // Contributions from an account

    // Post delivery
    mapping(address => uint256) private _balances;
    __unstable__TokenVault private _vault;

    event xProjectCrowdsaleDeployed(
        uint256 rate, // rate, 1 ETH = 100 SXT
        uint256 individualCap,
        address payable wallet, // wallet to send Ether //Always use a Multi-Sig wallet :)
        address tokenWallet, // wallet to pull SXT tokens
        IERC20 token, // the SXT token
        uint256 hardcap, // total hardcap (in wei)
        uint256 softcap, // total softcap (in wei)
        uint256 openingTime, // opening time in unix epoch seconds
        uint256 closingTime // closing time in unix epoch seconds
    );

    /**
     * @dev Constructor.
     */
    constructor(
        uint256 rate, // rate, 1 ETH = 100 SXT
        uint256 individualCap, // deposit limit per an individual (in wei)
        address payable wallet, // wallet to send Ether // Always use a Multi-Sig wallet :)
        address tokenWallet, // wallet to pull SXT tokens
        IERC20 token, // the SXT token
        uint256 hardcap, // total hardcap (in wei)
        uint256 softcap, // total softcap (in wei)
        uint256 openingTime, // opening time in unix epoch seconds
        uint256 closingTime // closing time in unix epoch seconds
    )
        public
        Crowdsale(rate, wallet, token)
        CappedCrowdsale(hardcap, softcap)
        IndividuallyCappedCrowdsale(individualCap)
        TimedCrowdsale(openingTime, closingTime)
        FinalizableCrowdsale()
        PostDeliveryCrowdsale()
        AllowanceCrowdsale(tokenWallet)
    {

        _vault = new __unstable__TokenVault();

        emit xProjectCrowdsaleDeployed(
            rate,
            individualCap,
            wallet,
            tokenWallet,
            token,
            hardcap,
            softcap,
            openingTime,
            closingTime
            
        );
    }

    // -- Configuration --

     /**
     * @dev Returns the amount contributed so far by a specific beneficiary.
     * @param beneficiary Address of contributor
     * @return Beneficiary contribution so far
     */
    function getContribution(address beneficiary) public view returns (uint256) {
        return _contributions[beneficiary];
    }

    // -- Post Delivery --

    /**
     * @return the balance of an account.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    // -- Hooks --
    /**
     * @dev Extend parent behavior requiring purchase to respect the beneficiary's funding cap.
     * @param beneficiary Token purchaser
     * @param weiAmount Amount of wei contributed
     */
    function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
        super._preValidatePurchase(beneficiary, weiAmount);
        // solhint-disable-next-line max-line-length
        // require(_contributions[beneficiary].add(weiAmount) <= _caps[beneficiary], "IndividuallyCappedCrowdsale: beneficiary's cap exceeded");
        require(_contributions[beneficiary].add(weiAmount) <= individualCap, "IndividuallyCappedCrowdsale: beneficiary's cap exceeded");
    }

    /**
     * @dev Extend parent behavior to update beneficiary contributions.
     * @param beneficiary Token purchaser
     * @param weiAmount Amount of wei contributed
     */
    function _updatePurchasingState(address beneficiary, uint256 weiAmount) internal {
        super._updatePurchasingState(beneficiary, weiAmount);
        _contributions[beneficiary] = _contributions[beneficiary].add(weiAmount);
    }
}
function getContribution(address beneficiary) public view returns (uint256) {
    return _contributions[beneficiary];
}

/**
 * @dev Returns the amount contributed so far by a specific beneficiary.
 * @param beneficiary Address of contributor
 * @return Beneficiary contribution so far
 */