contract CloneFactory is TieredOwnership {
  //event emits new contract address
  event Deployed(address indexed proxyAddress, bytes32 indexed salt) anonymous;
  //immutable template for cloning
  address public immutable proxyImplementation;

  /**
   * @notice The creating address becomes the owner
   * @dev Creates the base clonable template
   */
  constructor() TieredOwnership() {
    proxyImplementation = address(new CloneableProxy());
  }

  /**
   * @notice Clones an existing proxy and initializes the contract
   * @param beacon is the address of the beacon to the logic contract
   * @param salt is a bytes32 specific to the contract being cloned
   * @param data is the initialization data of the logic contract
   * Can only be called by the current owner.
   *
   * Emits a {Deployed} event.
   */
  function createProxy(address beacon, bytes32 salt, bytes memory data) external onlyOwner() {
    address payable clone = payable(Clones.cloneDeterministic(proxyImplementation, salt));
    CloneableProxy(clone).initialize(beacon, data);
    emit Deployed(clone, salt);
  }
}
/**
 * @title Telcoin, LLC.
 * @dev Implements Openzeppelin Audited Contracts
 *
 * @notice Contract is designed to make duplicates of a proxy contract
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
function createProxy(address beacon, bytes32 salt, bytes memory data) external onlyOwner() {
  address payable clone = payable(Clones.cloneDeterministic(proxyImplementation, salt));
  CloneableProxy(clone).initialize(beacon, data);
  emit Deployed(clone, salt);
}

/**
 * @notice Clones an existing proxy and initializes the contract
 * @param beacon is the address of the beacon to the logic contract
 * @param salt is a bytes32 specific to the contract being cloned
 * @param data is the initialization data of the logic contract
 * Can only be called by the current owner.
 *
 * Emits a {Deployed} event.
 */