Any public vault without a delegate can be drained
If a public vault is created without a delegate, delegate will have the value of `address(0)`. This is also the value returned by `ecrecover` for invalid signatures (for example, if v is set to a position number that is not 27 or 28), which allows a malicious actor to cause the signature validation to pass for arbitrary parameters, allowing them to drain a vault using a worthless NFT as collateral.\\nWhen a new Public Vault is created, the Router calls the `init()` function on the vault as follows:\\n```\\nVaultImplementation(vaultAddr).init(\\n  VaultImplementation.InitParams(delegate)\\n);\\n```\\n\\nIf a delegate wasn't set, this will pass `address(0)` to the vault. If this value is passed, the vault simply skips the assignment, keeping the delegate variable set to the default 0 value:\\n```\\nif (params.delegate != address(0)) {\\n  delegate = params.delegate;\\n}\\n```\\n\\nOnce the delegate is set to the zero address, any commitment can be validated, even if the signature is incorrect. This is because of a quirk in `ecrecover` which returns `address(0)` for invalid signatures. A signature can be made invalid by providing a positive integer that is not 27 or 28 as the `v` value. The result is that the following function call assigns recovered = address(0):\\n```\\n    address recovered = ecrecover(\\n      keccak256(\\n        encodeStrategyData(\\n          params.lienRequest.strategy,\\n          params.lienRequest.merkle.root\\n        )\\n      ),\\n      params.lienRequest.v,\\n      params.lienRequest.r,\\n      params.lienRequest.s\\n    );\\n```\\n\\nTo confirm the validity of the signature, the function performs two checks:\\n```\\nrequire(\\n  recovered == params.lienRequest.strategy.strategist,\\n  "strategist must match signature"\\n);\\nrequire(\\n  recovered == owner() || recovered == delegate,\\n  "invalid strategist"\\n);\\n```\\n\\nThese can be easily passed by setting the `strategist` in the params to `address(0)`. At this point, all checks will pass and the parameters will be accepted as approved by the vault.\\nWith this power, a borrower can create params that allow them to borrow the vault's full funds in exchange for a worthless NFT, allowing them to drain the vault and steal all the user's funds.
Issue Any public vault without a delegate can be drained\\nAdd a require statement that the recovered address cannot be the zero address:\\n```\\nrequire(recovered != address(0));\\n```\\n
All user's funds held in a vault with no delegate set can be stolen.
```\\nVaultImplementation(vaultAddr).init(\\n  VaultImplementation.InitParams(delegate)\\n);\\n```\\n