Skip to content

Commit d88a55b

Browse files
jgalatjxom
andauthored
fix: decodeEventLog mixing order of parameters (#3688)
* fix: keep unnamed args ordered when indexed are mixed * chore: changeset * Update tricky-hairs-pretend.md * Update decodeEventLog.test.ts * Update decodeEventLog.ts --------- Co-authored-by: jxom <7336481+jxom@users.noreply.github.com>
1 parent 4ba1569 commit d88a55b

File tree

3 files changed

+62
-9
lines changed

3 files changed

+62
-9
lines changed

.changeset/tricky-hairs-pretend.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"viem": patch
3+
---
4+
5+
Fixed ordering of decoded arguments in `decodeEventLog`.

src/utils/abi/decodeEventLog.test.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,49 @@ test('unnamed args: Transfer(address,address,uint256)', () => {
169169
})
170170
})
171171

172+
test('unnamed args: mixed ordering of indexed args', () => {
173+
const event = decodeEventLog({
174+
abi: [
175+
{
176+
inputs: [
177+
{
178+
indexed: true,
179+
type: 'address',
180+
},
181+
{
182+
indexed: false,
183+
type: 'uint256',
184+
},
185+
{
186+
indexed: true,
187+
type: 'address',
188+
},
189+
],
190+
name: 'Transfer',
191+
type: 'event',
192+
},
193+
],
194+
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
195+
topics: [
196+
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
197+
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
198+
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
199+
],
200+
})
201+
assertType<typeof event>({
202+
eventName: 'Transfer',
203+
args: ['0x', 1n, '0x'],
204+
})
205+
expect(event).toEqual({
206+
args: [
207+
'0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
208+
1n,
209+
'0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
210+
],
211+
eventName: 'Transfer',
212+
})
213+
})
214+
172215
test('Foo(string)', () => {
173216
const event = decodeEventLog({
174217
abi: [

src/utils/abi/decodeEventLog.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -131,19 +131,24 @@ export function decodeEventLog<
131131
const { name, inputs } = abiItem
132132
const isUnnamed = inputs?.some((x) => !('name' in x && x.name))
133133

134-
let args: any = isUnnamed ? [] : {}
134+
const args: any = isUnnamed ? [] : {}
135135

136136
// Decode topics (indexed args).
137-
const indexedInputs = inputs.filter((x) => 'indexed' in x && x.indexed)
137+
const indexedInputs = inputs
138+
.map((x, i) => [x, i] as const)
139+
.filter(([x]) => 'indexed' in x && x.indexed)
138140
for (let i = 0; i < indexedInputs.length; i++) {
139-
const param = indexedInputs[i]
141+
const [param, argIndex] = indexedInputs[i]
140142
const topic = argTopics[i]
141143
if (!topic)
142144
throw new DecodeLogTopicsMismatch({
143145
abiItem,
144146
param: param as AbiParameter & { indexed: boolean },
145147
})
146-
args[isUnnamed ? i : param.name || i] = decodeTopic({ param, value: topic })
148+
args[isUnnamed ? argIndex : param.name || argIndex] = decodeTopic({
149+
param,
150+
value: topic,
151+
})
147152
}
148153

149154
// Decode data (non-indexed args).
@@ -153,12 +158,12 @@ export function decodeEventLog<
153158
try {
154159
const decodedData = decodeAbiParameters(nonIndexedInputs, data)
155160
if (decodedData) {
156-
if (isUnnamed) args = [...args, ...decodedData]
157-
else {
158-
for (let i = 0; i < nonIndexedInputs.length; i++) {
161+
if (isUnnamed)
162+
for (let i = 0; i < inputs.length; i++)
163+
args[i] = args[i] ?? decodedData.shift()
164+
else
165+
for (let i = 0; i < nonIndexedInputs.length; i++)
159166
args[nonIndexedInputs[i].name!] = decodedData[i]
160-
}
161-
}
162167
}
163168
} catch (err) {
164169
if (strict) {

0 commit comments

Comments
 (0)