-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
encodeEventTopics() (and watchLogs()) do not handle anonymous events #4461
Description
Check existing issues
- I checked there isn't already an issue for the bug I encountered.
Viem Version
2.47.10
Current Behavior
encodeEventTopics() does not handle anonymous events properly.
It incorrectly uses the signature as the first log topic.
Expected Behavior
To correctly encode the log topics.
Steps To Reproduce
const rawEventAbiItem = [
{
name: 'RawEvent',
type: 'event',
anonymous: true,
inputs: [
{ name: 'topic0', type: 'bytes32', indexed: true },
{ name: 'topic1', type: 'bytes32', indexed: true },
{ name: 'topic2', type: 'bytes32', indexed: true },
{ name: 'topic3', type: 'bytes32', indexed: true },
],
},
] as const
test('anonymous event: no args', () => {
expect(encodeEventTopics({ abi: rawEventAbiItem })).toEqual([])
})
test('anonymous event: topic0', () => {
expect(
encodeEventTopics({
abi: rawEventAbiItem,
args: {
topic0:
'0x000000000000000000000000000000000000000000000000000000000000abcd',
},
}),
).toEqual([
'0x000000000000000000000000000000000000000000000000000000000000abcd',
null,
null,
null,
])
})
test('anonymous event: all topics', () => {
expect(
encodeEventTopics({
abi: rawEventAbiItem,
args: {
topic0:
'0x0000000000000000000000000000000000000000000000000000000000000000',
topic1:
'0x0000000000000000000000000000000000000000000000000000000000000001',
topic2:
'0x0000000000000000000000000000000000000000000000000000000000000002',
topic3:
'0x0000000000000000000000000000000000000000000000000000000000000003',
},
}),
).toEqual([
'0x0000000000000000000000000000000000000000000000000000000000000000',
'0x0000000000000000000000000000000000000000000000000000000000000001',
'0x0000000000000000000000000000000000000000000000000000000000000002',
'0x0000000000000000000000000000000000000000000000000000000000000003',
])
})Link to Minimal Reproducible Example
No response
Anything else?
I came across this issue while trying to find a workaround to specify the log topics directly.
encodeEventTopics() does not check abiItem.anonymous before setting the sigature as topic0.
viem/src/utils/abi/encodeEventTopics.ts
Line 124 in 14f77b7
| return [signature, ...topics] |
The logic itself is trivial to fix:
diff --git a/src/utils/abi/encodeEventTopics.ts b/src/utils/abi/encodeEventTopics.ts
index 21415b5..c1c8a29 100644
--- a/src/utils/abi/encodeEventTopics.ts
+++ b/src/utils/abi/encodeEventTopics.ts
@@ -94,9 +94,6 @@ export function encodeEventTopics<
if (abiItem.type !== 'event')
throw new AbiEventNotFoundError(undefined, { docsPath })
- const definition = formatAbiItem(abiItem)
- const signature = toEventSelector(definition as EventDefinition)
-
let topics: (Hex | Hex[] | null)[] = []
if (args && 'inputs' in abiItem) {
const indexedInputs = abiItem.inputs?.filter(
@@ -121,7 +118,15 @@ export function encodeEventTopics<
}) ?? []
}
}
- return [signature, ...topics]
+
+ // only prepend signature for non-anonymous events
+ if (!abiItem.anonymous) {
+ const definition = formatAbiItem(abiItem)
+ const signature = toEventSelector(definition as EventDefinition)
+ topics.unshift(signature)
+ }
+
+ return topics
}
export type EncodeArgErrorType =But a bigger issue is the return type being [Hex, ...(Hex | Hex[] | null)[]], making an empty array fail the typecheck.
Not sure how that should be handled since changing the return type to [] can break existing code.
Maybe it can be inferred based on the type of event?