Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Draft] EIP-2442 - LOGQUERYn opcodes #2442

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
113 changes: 113 additions & 0 deletions EIPS/eip-2442.md
@@ -0,0 +1,113 @@
---
eip: 2442
title: LOGQUERY(n) opcodes
author: pinkiebell (@pinkiebell)
discussions-to: https://ethereum-magicians.org/t/rfc-eip-2442-logqueryn-opcodes/3867
status: Draft
type: Standards Track
category: Core
created: 2019-12-19
---

## Abstract

This EIP specifies new opcodes `LOGQUERY(x)`, which mirrors the semantics of the `LOG(n)` opcodes to gain the support
for querying/filtering the most recent log event of the current contract/EVM context.

## Motivation

To better support stateless(light)-clients, layer-2 scaling solutions and similar applications,
gaining the ability to query the last emitted log event and having the log-data available inside a
contract has a huge benefit to an overall simpler system/application design.

In the context of optimistic-rollup solutions, one could imagine to use `LOG` events, corresponding `topics` as storage keys and log-data
as a way to signal state changes to light clients and simultaneously using it as a storage backend for the on-chain contract itself.

A rudimentary example:
```
// Layer-2 Bridge contract transfers AMOUNT of TOKEN from `Alice` to `Bob`.

let storageTopic = keccak256(Alice, Token)
// query Alice
let success = logquery1(memoryPtr, 0, 32, storageTopic)

// we had a past event
if (success) {
// the data of the log contains the uint256 balance
let aliceBalance = mload(memoryPtr)

if (aliceBalance >= AMOUNT) {
mstore(memoryPtr, aliceBalance - AMOUNT)
// update Alice's new balance
log1(memoryPtr, 32, storageTopic)

// Bob's new (pre) balance
mstore(memoryPtr, AMOUNT)
let storageTopic = keccak256(Bob, Token)
// query Bob
success = logquery1(memoryPtr, 0, 32, storageTopic)
if (success) {
// update Bob's balance
mstore(memoryPtr, mload(memoryPtr) + AMOUNT)
}
// log Bob's new balance
log1(memoryPtr, 32, storageTopic)
} else {
// Alice has not enough AMOUNT
revert()
}

} else {
// no event for (Alice, Token) emitted in the past - who is Alice?
revert()
}
```

Other solutions like validating log events with past block-hashes are inconvienent and also of limited use.
Additionally, there is no trustless way of verifying if any given log was the latest/most recent one.

## Specification

```
GAS_BASE = 100
GAS_BYTE = 3

```

`(t, f, s)` = copy `s` bytes from log's data at position `f` to mem at position `t`.

| Opcode | Hex | Gas cost | Notes |
| -------------------------------------------------- | ---- | --------------------------------- | ---------------------------------------------- |
| logquery0(t, f, s) | 0xb0 | `GAS_BASE + (s * GAS_BYTE)` | No topic filter - fetch most recent log |
| logquery1(t, f, s, topic1) | 0xb1 | `(GAS_BASE * 2) + (s * GAS_BYTE)` | Get last log with 1 topic and topic = `topic1` |
| logquery2(t, f, s, topic1, topic2) | 0xb2 | `(GAS_BASE * 3) + (s * GAS_BYTE)` | ... |
| logquery3(t, f, s, topic1, topic2, topic3) | 0xb3 | `(GAS_BASE * 4) + (s * GAS_BYTE)` | ... |
| logquery4(t, f, s, topic1, topic2, topic3, topic4) | 0xb4 | `(GAS_BASE * 5) + (s * GAS_BYTE)` | ... |


Common behaviour for all `logqueryX` opcodes:
- If there is no matching log
- Push `0` to stack and do not touch memory(`t`, `s`).
- If there is a matching log
- Push `1` to the stack and fill memory(`t` = memory pointer, `s` = size) with the log's `data` starting at `f` and size `s` bytes.
- If `f + s` is greater than the log's `data`, then pad the remaining length with `0`'s.

## Rationale

As described in the motivation section, this opcode is widely useful and should help the ongoing Eth1.x efforts.

## Backwards Compatibility

There are no backwards compatibility concerns.

## Test Cases

TBD

## Implementation

TBD

## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).