contract Deployer is Ownable {
    event Deployed(address deployedAddress);

    /**
     * Deploy a contract using create2
     */
    function deploy(
        bytes calldata _initCode, 
        bytes32 _salt
    ) external onlyOwner returns(address) {
        address deployedAddress = Create2.deploy(_salt, _initCode);
        emit Deployed(deployedAddress);
        return deployedAddress;
    }

    /**
     * Deploy a contract and execute a call to it in the same tx.
     * Useful for initializers
     */
    function deployAndCall(
        bytes calldata _initCode, 
        bytes32 _salt,
        bytes calldata _call
    ) external onlyOwner returns(address) {
        address deployedAddress = Create2.deploy(_salt, _initCode);
        (bool success, ) = deployedAddress.call(_call);
        require(success, "Call after deployment failed.");
        emit Deployed(deployedAddress);
        return deployedAddress;
    }

    /**
     * Compute the addresses of contracts created by this contract
     */
    function computeAddress(
        bytes calldata _initCode, 
        bytes32 _salt
    ) external view returns(address) {
        return Create2.computeAddress(_salt, _initCode);
    }

    /**
     * Compute the addresses of contracts created by this a deployer contract
     */
    function computeAddressFor(
        bytes calldata _initCode, 
        bytes32 _salt,
        address _deployer
    ) external pure returns(address) {
        return Create2.computeAddress(_salt, _initCode, _deployer);
    }
}
/**
 * Deploys contracts to deterministic addresses
 */
function computeAddress(
    bytes calldata _initCode, 
    bytes32 _salt
) external view returns(address) {
    return Create2.computeAddress(_salt, _initCode);
}

/**
 * Compute the addresses of contracts created by this contract
 */