contract AssetProtectable is Context {
  address private _assetProtector;
  mapping(address => bool) private _frozens;

  event AssetProtectorRoleTransferred(address indexed previousAssetProtector, address indexed newAssetProtector);
  event AccountFrozen(address indexed account);
  event AccountUnfrozen(address indexed account);
  event FrozenAccountWiped(address indexed account);

  /**
   * @dev Initializes the contract setting the deployer as the initial asset protector.
   */
  constructor() internal {
    address msgSender = _msgSender();
    _assetProtector = msgSender;
    emit AssetProtectorRoleTransferred(address(0), msgSender);
  }

  /**
   * @dev Returns the address of the current asset protector.
   */
  function assetProtector() public view returns (address) {
    return _assetProtector;
  }

  /**
   * @dev Throws if called by any account other than the asset protector.
   */
  modifier onlyAssetProtector() {
    require(_assetProtector == _msgSender(), "AssetProtectable: caller is not the asset protector");
    _;
  }

  /**
   * @dev Transfers asset protector role of the contract to a new account (`newAssetProtector`).
   */
  function transferAssetProtectorRole(address newAssetProtector) public virtual {
    require(newAssetProtector != address(0), "AssetProtectable: new asset protector is the zero address");
    emit AssetProtectorRoleTransferred(_assetProtector, newAssetProtector);
    _assetProtector = newAssetProtector;
  }

  /**
   * @dev Returns whether the address is frozen.
   */
  function isFrozen(address account) public view returns (bool) {
    return _frozens[account];
  }

  /**
   * @dev Freeze account, only asset protector can freeze
   */
  function _freeze(address account) internal {
    _frozens[account] = true;
    emit AccountFrozen(account);
  }

  /**
   * @dev Unfreeze account, only asset protector can unfreeze
   */
  function _unfreeze(address account) internal {
    _frozens[account] = false;
    emit AccountUnfrozen(account);
  }
}
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an asset protector) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the asset protect account will be the one that deploys the contract. This
 * can later be changed with {transferAssetProtectorRole}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyAssetProtector`, which can be applied to your functions to restrict their use to
 * the asset protector.
 */
function _freeze(address account) internal {
  _frozens[account] = true;
  emit AccountFrozen(account);
}

/**
 * @dev Freeze account, only asset protector can freeze
 */