contract Benefactor is Ownable {
    //
    // Variables
    // -----------------------------------------------------------------------------------------------------------------
    address[] internal beneficiaries;
    mapping(address => uint256) internal beneficiaryIndexByAddress;

    //
    // Events
    // -----------------------------------------------------------------------------------------------------------------
    event RegisterBeneficiaryEvent(address beneficiary);
    event DeregisterBeneficiaryEvent(address beneficiary);

    //
    // Functions
    // -----------------------------------------------------------------------------------------------------------------
    /// @notice Register the given beneficiary
    /// @param beneficiary Address of beneficiary to be registered
    function registerBeneficiary(address beneficiary)
    public
    onlyDeployer
    notNullAddress(beneficiary)
    returns (bool)
    {
        if (beneficiaryIndexByAddress[beneficiary] > 0)
            return false;

        beneficiaries.push(beneficiary);
        beneficiaryIndexByAddress[beneficiary] = beneficiaries.length;

        // Emit event
        emit RegisterBeneficiaryEvent(beneficiary);

        return true;
    }

    /// @notice Deregister the given beneficiary
    /// @param beneficiary Address of beneficiary to be deregistered
    function deregisterBeneficiary(address beneficiary)
    public
    onlyDeployer
    notNullAddress(beneficiary)
    returns (bool)
    {
        if (beneficiaryIndexByAddress[beneficiary] == 0)
            return false;

        uint256 idx = beneficiaryIndexByAddress[beneficiary] - 1;
        if (idx < beneficiaries.length - 1) {
            // Remap the last item in the array to this index
            beneficiaries[idx] = beneficiaries[beneficiaries.length - 1];
            beneficiaryIndexByAddress[beneficiaries[idx]] = idx + 1;
        }
        beneficiaries.length--;
        beneficiaryIndexByAddress[beneficiary] = 0;

        // Emit event
        emit DeregisterBeneficiaryEvent(beneficiary);

        return true;
    }

    /// @notice Gauge whether the given address is the one of a registered beneficiary
    /// @param beneficiary Address of beneficiary
    /// @return true if beneficiary is registered, else false
    function isRegisteredBeneficiary(address beneficiary)
    public
    view
    returns (bool)
    {
        return beneficiaryIndexByAddress[beneficiary] > 0;
    }

    /// @notice Get the count of registered beneficiaries
    /// @return The count of registered beneficiaries
    function registeredBeneficiariesCount()
    public
    view
    returns (uint256)
    {
        return beneficiaries.length;
    }
}
/**
 * @title Benefactor
 * @notice An ownable that contains registered beneficiaries
 */
function deregisterBeneficiary(address beneficiary)
public
onlyDeployer
notNullAddress(beneficiary)
returns (bool)
{
    if (beneficiaryIndexByAddress[beneficiary] == 0)
        return false;

    uint256 idx = beneficiaryIndexByAddress[beneficiary] - 1;
    if (idx < beneficiaries.length - 1) {
        // Remap the last item in the array to this index
        beneficiaries[idx] = beneficiaries[beneficiaries.length - 1];
        beneficiaryIndexByAddress[beneficiaries[idx]] = idx + 1;
    }
    beneficiaries.length--;
    beneficiaryIndexByAddress[beneficiary] = 0;

    // Emit event
    emit DeregisterBeneficiaryEvent(beneficiary);

    return true;
}

/// @notice Deregister the given beneficiary
/// @param beneficiary Address of beneficiary to be deregistered