Verifiers need to be pure, but it's very difficult to validate pureness
After the initial audit, a “verifier” was introduced to the `OrchidLottery` code. Each `Pot` can have an associated `OrchidVerifier`. This is a contract with a `good()` function that accepts three parameters:\\n```\\nfunction good(bytes calldata shared, address target, bytes calldata receipt) external pure returns (bool);\\n```\\n\\nThe verifier returns a boolean indicating whether a given micropayment should be allowed or not. An example use case is a verifier that only allows certain `target` addresses to be paid. In this case, `shared` (a single value for a given Pot) is a merkle root, `target` is (as always) the address being paid, and `receipt` (specified by the payment recipient) is a merkle proof that the `target` address is within the merkle tree with the given root.\\nA server providing bandwidth needs to know whether to accept a certain receipt. To do that, it needs to know that at some time in the future, a call to the verifier's `good()` function with a particular set of parameters will return `true`. The proposed scheme for determining that is for the server to run the contract's code locally and ensure that it returns `true` and that it doesn't execute any EVM opcodes that would read state. This prevents, for example, a contract from returning `true` until a certain timestamp and then start returning `false`. If a contract could do that, the server would be tricked into providing bandwidth without then receiving payment.\\nUnfortunately, this simple scheme is insufficient. As a simple example, a verifier contract could be created with the `CREATE2` opcode. It could be demonstrated that it reads no state when `good()` is called. Then the contract could be destroyed by calling a function that performs a `SELFDESTRUCT`, and it could be replaced via another `CREATE2` call with different code.\\nThis could be mitigated by rejecting any verifier contract that contains the `SELFDESTRUCT` opcode, but this would also catch harmless occurrences of that particular byte. https://gist.github.com/Arachnid/e8f0638dc9f5687ff8170a95c47eac1e attempts to find `SELFDESTRUCT` opcodes but fails to account for tricks where the `SELFDESTRUCT` appears to be data but can actually be executed. (See Recmo's comment.) In general, this approach is difficult to get right and probably requires full data flow analysis to be correct.\\nAnother possible mitigation is to use a factory contract to deploy the verifiers, guaranteeing that they're not created with `CREATE2`. This should render `SELFDESTRUCT` harmless, but there's no guarantee that future forks won't introduce new vectors here.\\nFinally, requiring servers to implement potentially complex contract validation opens up potential for denial-of-service attacks. A server will have to implement mitigations to prevent repeatedly checking the same verifier or spending inordinate resources checking a maliciously crafted contract (e.g. one with high branching factors).
The verifiers add quite a bit of complexity and risk. We recommend looking for an alternative approach, such as including a small number of vetted verifiers (e.g. a merkle proof verifier) or having servers use their own “allow list” for verifiers that they trust.
```\\nfunction good(bytes calldata shared, address target, bytes calldata receipt) external pure returns (bool);\\n```\\n