contract RefundableCrowdsale is FinalizableCrowdsale {
    using SafeMath for uint256;
    using Votings for Votings.Voting;

    event FundsWithdraw(uint256 indexed etherAmount, address indexed account);

    // Current vote processes
    Votings.Voting private _votings;

    // refund escrow used to hold funds while crowdsale is running
    RefundEscrow private _escrow;

    /**
     * @dev Constructor, creates RefundEscrow.
     */
    constructor () public {
        _escrow = new RefundEscrow(wallet());
    }

    /**
     * @dev Investors can claim refunds here if crowdsale is unsuccessful
     * @param refundee Whose refund will be claimed.
     */
    function claimRefund(address payable refundee) public {
        require(finalized());
        require(!goalReached());

        _escrow.withdraw(refundee);
    }

    function beneficiaryWithdraw(uint256 etherAmount, address payable account) AdminOnly public {
        if (goalReached() && consensus(etherAmount, address(account))) {
            _escrow.customWithdraw(etherAmount * 1e18, account);
            emit FundsWithdraw(etherAmount * 1e18, address(account));
        }
    }

    /**
     * @dev escrow finalization task, called when finalize() is called
     */
    function _finalization() internal {
        if (goalReached()) {
            _escrow.close();
            _escrow.beneficiaryWithdraw();
        } else {
            uint256 day = 86400;
            require(block.timestamp > softcapDeadline() + day);
            _escrow.enableRefunds();
        }

        super._finalization();
    }

    /**
     * @dev Overrides Crowdsale fund forwarding, sending funds to escrow.
     */
    function _forwardFunds(uint256 weiAmount) internal {
        _escrow.deposit.value(weiAmount)(msg.sender);
    }

    /**
   * @dev require (N/2)+1 admins to be agreed with the proposal
   * @return do all admins agreed with the proposal?
   */
    function consensus(uint256 etherAmount, address account) private returns (bool) {
        return _votings.voteAndCheck(
            Helpers.mixId(account, etherAmount),
            msg.sender,
            Helpers.majority(countAdmins())
        );
    }
}
/**
 * @title RefundableCrowdsale
 * @dev Extension of FinalizableCrowdsale contract that adds a funding goal, and the possibility of users
 * getting a refund if goal is not met.
 *
 * Deprecated, use RefundablePostDeliveryCrowdsale instead. Note that if you allow tokens to be traded before the goal
 * is met, then an attack is possible in which the attacker purchases tokens from the crowdsale and when they sees that
 * the goal is unlikely to be met, they sell their tokens (possibly at a discount). The attacker will be refunded when
 * the crowdsale is finalized, and the users that purchased from them will be left with worthless tokens.
 */
function _forwardFunds(uint256 weiAmount) internal {
    _escrow.deposit.value(weiAmount)(msg.sender);
}

/**
 * @dev Overrides Crowdsale fund forwarding, sending funds to escrow.
 */