low

Pure functions can emit logs

Reward

Total

455.95 USDC

Selected
455.95 USDC
Selected Submission

Pure functions can emit logs

Severity

Medium Risk

Relevant GitHub Links

https://github.com/vyperlang/vyper/issues/3141

Summary

Pure functions are allowed to emit logs.

Vulnerability Details

While pure functions are expected to be fully equivalent at any time, this is a false assumption that has been uncovered in the ChainSecurity review, because blockhash can be used. A built-in that has been forgotten is raw_log, which emits logs thanks to the LOG<N> opcode. For instance, this compiles just fine:

@external
@pure
def loggg(_topic: bytes32, _data: Bytes[100]):
    raw_log([_topic], _data)

This is a write operation, while pure functions should only allow read access, thus breaking assumptions with pure functions.

Impact

This could be used maliciously for instance for implementors of pure functions. They should be called with the STATICCALL opcode which should throw an exception for any executed operation including CREATE, CREATE2, LOG0, LOG1, LOG2, LOG3, LOG4 SSTORE SELFDESTRUCT, and CALL with a non-zero value as described in the EIP-214 (did they missed delegatecall ?). In this case, STATICCALL will be used and when log is going to be emitted, the call will revert, which could freeze a contract.

Tools Used

Manual review

Recommendations

Ban raw_log from pure functions.