contract IdentityFactory {
	event LogDeployed(address addr, uint256 salt);

	address public creator;
	constructor() public {
		creator = msg.sender;
	}

	function deploy(bytes memory code, uint256 salt) public {
		deploySafe(code, salt);
	}

	// When the relayer needs to act upon an /execute call, it'll either call execute on the Identity directly
	// if it's already deployed, or call `deployAndExecute` if the account is still counterfactual
	function deployAndExecute(
		bytes memory code, uint256 salt,
		Identity.Transaction[] memory txns, bytes32[3][] memory signatures
	) public {
		address addr = deploySafe(code, salt);
		Identity(addr).execute(txns, signatures);
	}

	// When the relayer needs to do routines, it'll either call executeRoutines on the Identity directly
	// if it's already deployed, or call `deployAndRoutines` if the account is still counterfactual
	function deployAndRoutines(
		bytes memory code, uint256 salt,
		Identity.RoutineAuthorization memory auth, Identity.RoutineOperation[] memory operations
	) public {
		address addr = deploySafe(code, salt);
		Identity(addr).executeRoutines(auth, operations);
	}

	// Withdraw the earnings from various fees (deploy fees and execute fees earned cause of `deployAndExecute`)
	function withdraw(address tokenAddr, address to, uint256 tokenAmount) public {
		require(msg.sender == creator, 'ONLY_CREATOR');
		SafeERC20.transfer(tokenAddr, to, tokenAmount);
	}

	// This is done to mitigate possible frontruns where, for example, deploying the same code/salt via deploy()
	// would make a pending deployAndExecute fail
	// The way we mitigate that is by checking if the contract is already deployed and if so, we continue execution
	function deploySafe(bytes memory code, uint256 salt) internal returns (address) {
		address expectedAddr = address(uint160(uint256(
			keccak256(abi.encodePacked(byte(0xff), address(this), salt, keccak256(code)))
		)));
		uint size;
		assembly { size := extcodesize(expectedAddr) }
		// If there is code at that address, we can assume it's the one we were about to deploy,
		// because of how CREATE2 and keccak256 works
		if (size == 0) {
			address addr;
			assembly { addr := create2(0, add(code, 0x20), mload(code), salt) }
			require(addr != address(0), 'FAILED_DEPLOYING');
			require(addr == expectedAddr, 'FAILED_MATCH');
			emit LogDeployed(addr, salt);
		}
		return expectedAddr;
	}
}
function withdraw(address tokenAddr, address to, uint256 tokenAmount) public {
	require(msg.sender == creator, 'ONLY_CREATOR');
	SafeERC20.transfer(tokenAddr, to, tokenAmount);
}

// Withdraw the earnings from various fees (deploy fees and execute fees earned cause of `deployAndExecute`)