Vyper: VIP Structs in Events

Created on 3 Jan 2019  路  6Comments  路  Source: vyperlang/vyper

Simple Summary

Allow emitting structs in events

Abstract

ABIv2 will allow emitting structs inside events.
This behavior is not well-defined (@davesque please confirm).

Motivation

Working with structs as input arguments, it may be useful to emit structs inside events for the client-side to use after a transaction has been mined e.g. a Deposit transaction in Plasma.

As mentioned by @charles-cooper in #1019

Specification

Specification is WIP, but here are a few possibilities:

Directly outputing a struct:

struct Transaction:
    prevBlkNum: uint256
    tokenId: uint256
    newOwner: address
    signature: bytes[65]  # VRS

DepositAdded: event({txn: Transaction})

def foo(txn: Transaction):
    log.DepositAdded(txn)

Outputting only certain members of a struct:

# Should we allow indexing event args in this way?
DepositAdded: event({tokenId: uint256, newOwner: address})

def foo(txn: Transaction):
    # Compiles to `log.DepositAdded(txn.tokenId, txn.newOwner)`
    log.DepositAdded(**txn)  # because who doesn't love kwargs?

Indexing:

# Do we allow structs to be indexed? ABIv2 is inconclusive I believe
DepositAdded: event({txn: indexed(Transaction)})

# Should we allow indexing event args in this way?
DepositAdded: event({tokenId: indexed(uint256), newOwner: address})

# Should we allow indexing members indirectly?
DepositAdded: event({txn: Transaction}, indexed=[txn.newOwner, txn.tokenId])

Backwards Compatibility

No backwards compatibility issues

Copyright

Copyright and related rights waived via CC0

Approved

All 6 comments

@fubuloubu I believe that information included in an event is encoded as arguments of a functional call would be minus any function selector at the beginning. This would include structs which would be encoded as tuples. Source is second sentence in this section of the current ABI spec: https://solidity.readthedocs.io/en/develop/abi-spec.html#argument-encoding

@fubuloubu I like the syntax for directly outputting a struct but I think the member selection is too magical. Users should have to specify which fields they want to log/index.

Re. indexing on a struct, according the EVM spec, each LOG topic is one word, so we would have to apply a map from struct to uint256/bytes32 (e.g. keccak256) and I think that is overfunctioning on behalf of the user. Besides, the topic data is not accessible so I'm having trouble thinking of a case where somebody would want to index a struct but not already have the hash.

I think Solidity uses the ABIv2 encoding but I'm not sure if it is packed or unpacked. For compatibility we should use whatever it uses.

According to solidity team https://gitter.im/ethereum/solidity-dev?at=5c3328241948ad07e8000c16

non-indexed structs should be abi-encoded, indexed structs should be packed and hashed.

"packed and hashed" hmm. So is it included both as a hash and as an ABI-encoded, unindexed data?

Not automatically. If you wanted to do that you would have to include it twice, like event Log(indexed Foo foo, Foo foo). It seems cumbersome but since logging costs a decent amount of gas the programmer should have control over those things.

I guess it would be helpful if the struct was a transaction, and you were waiting on it to be confirmed in the contract, sort of like "transaction hash was mined!"

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ben-kaufman picture ben-kaufman  路  3Comments

michwill picture michwill  路  3Comments

jacqueswww picture jacqueswww  路  4Comments

fubuloubu picture fubuloubu  路  3Comments

nrryuya picture nrryuya  路  3Comments