skalenetwork / skaled

Running more than 20 production blockchains, SKALED is Ethereum-compatible, high performance C++ Proof-of-Stake client, tools and libraries. Uses SKALE consensus as a blockchain consensus core. Includes dynamic Oracle. Implements file storage and retrieval as an EVM extension.
https://skale.network
GNU General Public License v3.0
84 stars 40 forks source link

`eth_subscribe` `logs` fails on go-ethereum because SKALE logs does not conform to EIP-1474 #1821

Open Darkness4 opened 8 months ago

Darkness4 commented 8 months ago

Describe the bug

Hello, with go-ethereum, I'm unable to parse any logs does not conform to EIP-1474: logIndex and transactionIndex returns 0 instead 0x0.

go-ethereum parses JSON logs in this file. By using hexutil.Uint, go-ethereum parse the hex string of logIndex, transactionIndex and blockNumber JSON to a uint.

This is because, according to EIP-1474, logIndex, transactionIndex and blockNumber follows the rules of a Quantity:

A Quantity value MUST be hex-encoded. A Quantity value MUST be "0x"-prefixed. A Quantity value MUST be expressed using the fewest possible hex digits per byte. A Quantity value MUST express zero as "0x0".

go-ethereum fails to parse logs on SKALE because SKALE (or at least the Titan AI Hub testnet) returns a payload where zero is 0 instead of "0x0". The returned error is json: cannot unmarshal non-string into Go struct field Log.logIndex of type hexutil.Uint

To Reproduce PoC: https://github.com/Darkness4/skale-log-failure-poc

Steps to reproduce the behavior: Run SubscribeFilterLogs with a chan types.Log:

func watchWithEthereum(
    ctx context.Context,
    contractAddress common.Address,
    ws *ethclient.Client,
) {
    logs := make(chan types.Log)
    query := ethereum.FilterQuery{
        Addresses: []common.Address{contractAddress},
    }
    sub, err := ws.SubscribeFilterLogs(context.Background(), query, logs)
    if err != nil {
        panic(err)
    }
    defer sub.Unsubscribe()

    close(ready)

    for {
        select {
        case err := <-sub.Err():
            if err != nil {
                panic(err) // json: cannot unmarshal non-string into Go struct field Log.logIndex of type hexutil.Uint
            }
        case <-ctx.Done():
            return
        case l := <-logs:
            fmt.Println("Event received:", l)
            close(done)
        }
    }
}

Expected behavior Got JSON:

{
  "address": "0x13974b7ea852723c21ea11a9d8310757eb959d28",
  "blockHash": "0x90cb200abbc11a6623a9ac298f7b5034532b9ce4ce12662fb61fe46fa582510e",
  "blockNumber": "0x15bc9",
  "data": "0x00...",
  "logIndex": 0,
  "topics": [
    "0xc49fa2d8e562e80e750f98e95e2178dc3201633e4f247b6474aa6d8fafe29dba"
  ],
  "transactionHash": "0x5116086a024d0c2db69735ad7d6507b2d181053e7c5047c15aa3d17584780a3f",
  "transactionIndex": 0
}

Expected JSON:

{
  "address": "0x13974b7ea852723c21ea11a9d8310757eb959d28",
  "blockHash": "0x90cb200abbc11a6623a9ac298f7b5034532b9ce4ce12662fb61fe46fa582510e",
  "blockNumber": "0x15bc9",
  "data": "0x00...",
  "logIndex": "0x0",
  "topics": [
    "0xc49fa2d8e562e80e750f98e95e2178dc3201633e4f247b6474aa6d8fafe29dba"
  ],
  "transactionHash": "0x5116086a024d0c2db69735ad7d6507b2d181053e7c5047c15aa3d17584780a3f",
  "transactionIndex": "0x0"
}

SKALE should return an hexadecimal string for logIndex and transactionIndex.

DmytroNazarenko commented 8 months ago

Hi @Darkness4 ! Thanks for reporting this issue, it is addressed to the following release