GitHub Security Advisory: GHSA-vgf2-gvx8-xwc3
Package: vyper (PIP)
Severity: LOW (CVSS 0.0)
CWE: CWE-670: Always-Incorrect Control Flow Implementation, CWE-703: Improper Check or Handling of Exceptional Conditions
Vulnerable versions: < 0.4.1
Patched in: unpatched

Summary: Vyper Does Not Check the Success of Certain Precompile Calls

Details:
### Summary

When the Vyper Compiler uses the precompiles EcRecover (0x1) and Identity (0x4), the success flag of the call is not checked. As a consequence an attacker can provide a specific amount of gas to make these calls fail but let the overall execution continue. Then the execution result can be incorrect.

Based on EVM's rules, after the failed precompile the remaining code has only 1/64 of the pre-call-gas left (as 63/64 were forwarded and spent). Hence, only fairly simple executions can follow the failed precompile calls. Therefore, we found no significantly impacted real-world contracts.

The fix is tracked in https://github.com/vyperlang/vyper/pull/4451.

### Details


#### The relevant precompiles

##### EcRecover

EcRecover is used in vyper's `ecrecover` built-in. As the precompile consumes 3000 gas, any execution after an out-of-gas EcRecover call has at most 47 gas left.

##### Identity

- The Identity precompile is used in vyper to perform memory copy operations. As its cost is variable, a variable amount of gas might be left after a failed call. The bigger the copy operation, the more gas can be left. Hence, a failed call to Identity could theoretically be followed by successful storage changes or emitted events.
- Identity is no longer used when `evm-version` `cancun` is used (because `MCOPY` is used instead). In 0.4.0 `cancun` is default, in 0.3.10 `cancun` is an option, otherwise `cancun` is not available. As only pre-`cancun` versions are relevant, we don't have to consider transient storage operations succeeding a failed call to Identity.

#### The other precompiles

- Calls to `Sha2`, `ecAdd`, and `ecMul` have success checks and have had them for a long time.
- The precompiles `modexp`, `ripe`, `blake`, `ecPairing`, and `Point Evaluation` have no builtins in vyper.


### PoC

In the following we provide concrete examples of incorrectly generated bytecode. These examples are not optimized, but rather Proof-of-Concepts. The list is also not exhaustive.

#### `ecrecover` use

- Affected versions: 0.2.0 - 0.4.0 
- For older compiler versions (<=0.3.9) it behaves similarly to this [older advisory](https://github.com/vyperlang/vyper/security/advisories/GHSA-f5x6-7qgp-jhf3). As no data is returned, the previous value of the memory word is returned to the user. Hence, any dirty bytes might be returned. Contracts with older compiler versions and `ecrecover` were checked.
- For new vyper versions, the output buffer is zeroed, so when the call fails zero is returned. This is an incorrect result, but developers should anyway check for 0 as a failure case. Hence, this is unlikely to result in issues. However, we did search for such cases.
- As mentioned above at most 47 gas is left after the failed call, hence a `return` is the most realistic scenario to be attacked.

Vulnerable Code:
```py
@external
@view
def foo(hash: bytes32, v: uint256, r:uint256, s:uint256) -> address:
    return ecrecover(hash, v, r, s)
```

Problematic Call:
```p