Allow emitting structs in events
ABIv2 will allow emitting structs inside events.
This behavior is not well-defined (@davesque please confirm).
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 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])
No backwards compatibility issues
Copyright and related rights waived via CC0
@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!"