viem 2.0.10 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/_cjs/chains/definitions/baseSepolia.js +4 -0
  3. package/_cjs/chains/definitions/baseSepolia.js.map +1 -1
  4. package/_cjs/chains/definitions/holesky.js +6 -0
  5. package/_cjs/chains/definitions/holesky.js.map +1 -1
  6. package/_cjs/chains/definitions/lightlinkPegasus.js +30 -0
  7. package/_cjs/chains/definitions/lightlinkPegasus.js.map +1 -0
  8. package/_cjs/chains/definitions/lightlinkPhoenix.js +30 -0
  9. package/_cjs/chains/definitions/lightlinkPhoenix.js.map +1 -0
  10. package/_cjs/chains/definitions/neonMainnet.js +6 -1
  11. package/_cjs/chains/definitions/neonMainnet.js.map +1 -1
  12. package/_cjs/chains/definitions/palm.js +32 -0
  13. package/_cjs/chains/definitions/palm.js.map +1 -0
  14. package/_cjs/chains/definitions/palmTestnet.js +33 -0
  15. package/_cjs/chains/definitions/palmTestnet.js.map +1 -0
  16. package/_cjs/chains/index.js +11 -3
  17. package/_cjs/chains/index.js.map +1 -1
  18. package/_cjs/errors/cursor.js +13 -1
  19. package/_cjs/errors/cursor.js.map +1 -1
  20. package/_cjs/errors/version.js +1 -1
  21. package/_cjs/errors/version.js.map +1 -1
  22. package/_cjs/utils/abi/decodeAbiParameters.js +117 -126
  23. package/_cjs/utils/abi/decodeAbiParameters.js.map +1 -1
  24. package/_cjs/utils/abi/decodeEventLog.js +7 -4
  25. package/_cjs/utils/abi/decodeEventLog.js.map +1 -1
  26. package/_cjs/utils/cursor.js +40 -3
  27. package/_cjs/utils/cursor.js.map +1 -1
  28. package/_cjs/utils/encoding/fromBytes.js +2 -2
  29. package/_cjs/utils/encoding/fromBytes.js.map +1 -1
  30. package/_cjs/utils/encoding/fromRlp.js +1 -1
  31. package/_cjs/utils/encoding/fromRlp.js.map +1 -1
  32. package/_esm/chains/definitions/baseSepolia.js +4 -0
  33. package/_esm/chains/definitions/baseSepolia.js.map +1 -1
  34. package/_esm/chains/definitions/holesky.js +6 -0
  35. package/_esm/chains/definitions/holesky.js.map +1 -1
  36. package/_esm/chains/definitions/lightlinkPegasus.js +27 -0
  37. package/_esm/chains/definitions/lightlinkPegasus.js.map +1 -0
  38. package/_esm/chains/definitions/lightlinkPhoenix.js +27 -0
  39. package/_esm/chains/definitions/lightlinkPhoenix.js.map +1 -0
  40. package/_esm/chains/definitions/neonMainnet.js +6 -1
  41. package/_esm/chains/definitions/neonMainnet.js.map +1 -1
  42. package/_esm/chains/definitions/palm.js +29 -0
  43. package/_esm/chains/definitions/palm.js.map +1 -0
  44. package/_esm/chains/definitions/palmTestnet.js +30 -0
  45. package/_esm/chains/definitions/palmTestnet.js.map +1 -0
  46. package/_esm/chains/index.js +4 -0
  47. package/_esm/chains/index.js.map +1 -1
  48. package/_esm/errors/cursor.js +11 -0
  49. package/_esm/errors/cursor.js.map +1 -1
  50. package/_esm/errors/version.js +1 -1
  51. package/_esm/errors/version.js.map +1 -1
  52. package/_esm/utils/abi/decodeAbiParameters.js +145 -140
  53. package/_esm/utils/abi/decodeAbiParameters.js.map +1 -1
  54. package/_esm/utils/abi/decodeEventLog.js +7 -4
  55. package/_esm/utils/abi/decodeEventLog.js.map +1 -1
  56. package/_esm/utils/cursor.js +41 -4
  57. package/_esm/utils/cursor.js.map +1 -1
  58. package/_esm/utils/encoding/fromBytes.js +2 -2
  59. package/_esm/utils/encoding/fromBytes.js.map +1 -1
  60. package/_esm/utils/encoding/fromRlp.js +1 -1
  61. package/_esm/utils/encoding/fromRlp.js.map +1 -1
  62. package/_types/chains/definitions/baseSepolia.d.ts +4 -0
  63. package/_types/chains/definitions/baseSepolia.d.ts.map +1 -1
  64. package/_types/chains/definitions/holesky.d.ts +5 -11
  65. package/_types/chains/definitions/holesky.d.ts.map +1 -1
  66. package/_types/chains/definitions/lightlinkPegasus.d.ts +35 -0
  67. package/_types/chains/definitions/lightlinkPegasus.d.ts.map +1 -0
  68. package/_types/chains/definitions/lightlinkPhoenix.d.ts +35 -0
  69. package/_types/chains/definitions/lightlinkPhoenix.d.ts.map +1 -0
  70. package/_types/chains/definitions/neonMainnet.d.ts +6 -1
  71. package/_types/chains/definitions/neonMainnet.d.ts.map +1 -1
  72. package/_types/chains/definitions/palm.d.ts +33 -0
  73. package/_types/chains/definitions/palm.d.ts.map +1 -0
  74. package/_types/chains/definitions/palmTestnet.d.ts +33 -0
  75. package/_types/chains/definitions/palmTestnet.d.ts.map +1 -0
  76. package/_types/chains/index.d.ts +4 -0
  77. package/_types/chains/index.d.ts.map +1 -1
  78. package/_types/errors/cursor.d.ts +10 -0
  79. package/_types/errors/cursor.d.ts.map +1 -1
  80. package/_types/errors/version.d.ts +1 -1
  81. package/_types/errors/version.d.ts.map +1 -1
  82. package/_types/utils/abi/decodeAbiParameters.d.ts +18 -19
  83. package/_types/utils/abi/decodeAbiParameters.d.ts.map +1 -1
  84. package/_types/utils/abi/decodeEventLog.d.ts.map +1 -1
  85. package/_types/utils/cursor.d.ts +13 -3
  86. package/_types/utils/cursor.d.ts.map +1 -1
  87. package/chains/definitions/baseSepolia.ts +4 -0
  88. package/chains/definitions/holesky.ts +6 -0
  89. package/chains/definitions/lightlinkPegasus.ts +27 -0
  90. package/chains/definitions/lightlinkPhoenix.ts +27 -0
  91. package/chains/definitions/neonMainnet.ts +6 -1
  92. package/chains/definitions/palm.ts +29 -0
  93. package/chains/definitions/palmTestnet.ts +30 -0
  94. package/chains/index.ts +4 -0
  95. package/errors/cursor.ts +13 -0
  96. package/errors/version.ts +1 -1
  97. package/package.json +1 -1
  98. package/utils/abi/decodeAbiParameters.ts +226 -249
  99. package/utils/abi/decodeEventLog.ts +9 -4
  100. package/utils/cursor.ts +53 -6
  101. package/utils/encoding/fromBytes.ts +2 -2
  102. package/utils/encoding/fromRlp.ts +1 -1
@@ -1,341 +1,284 @@
1
- import type {
2
- AbiParameter,
3
- AbiParameterToPrimitiveType,
4
- AbiParametersToPrimitiveTypes,
5
- } from 'abitype'
1
+ import type { AbiParameter, AbiParametersToPrimitiveTypes } from 'abitype'
2
+
3
+ import type { ByteArray, Hex } from '../../types/misc.js'
6
4
 
7
5
  import {
8
6
  AbiDecodingDataSizeTooSmallError,
9
- type AbiDecodingDataSizeTooSmallErrorType,
10
- AbiDecodingOffsetOutOfBoundsError,
11
7
  AbiDecodingZeroDataError,
12
- type AbiDecodingZeroDataErrorType,
13
8
  InvalidAbiDecodingTypeError,
14
9
  type InvalidAbiDecodingTypeErrorType,
15
10
  } from '../../errors/abi.js'
16
- import type { Hex } from '../../types/misc.js'
11
+ import type { ErrorType } from '../../errors/utils.js'
17
12
  import {
18
13
  type ChecksumAddressErrorType,
19
14
  checksumAddress,
20
15
  } from '../address/getAddress.js'
16
+ import { type Cursor, createCursor } from '../cursor.js'
21
17
  import { type SizeErrorType, size } from '../data/size.js'
22
- import { type SliceErrorType, slice } from '../data/slice.js'
18
+ import { type SliceBytesErrorType, sliceBytes } from '../data/slice.js'
23
19
  import { type TrimErrorType, trim } from '../data/trim.js'
24
20
  import {
25
- type HexToBigIntErrorType,
26
- type HexToBoolErrorType,
27
- type HexToNumberErrorType,
28
- type HexToStringErrorType,
29
- hexToBigInt,
30
- hexToBool,
31
- hexToNumber,
32
- hexToString,
33
- } from '../encoding/fromHex.js'
34
-
35
- import type { ErrorType } from '../../errors/utils.js'
36
- import {
37
- type GetArrayComponentsErrorType,
38
- getArrayComponents,
39
- } from './encodeAbiParameters.js'
21
+ type BytesToBigIntErrorType,
22
+ type BytesToBoolErrorType,
23
+ type BytesToNumberErrorType,
24
+ type BytesToStringErrorType,
25
+ bytesToBigInt,
26
+ bytesToBool,
27
+ bytesToNumber,
28
+ bytesToString,
29
+ } from '../encoding/fromBytes.js'
30
+ import { type HexToBytesErrorType, hexToBytes } from '../encoding/toBytes.js'
31
+ import { type BytesToHexErrorType, bytesToHex } from '../encoding/toHex.js'
32
+ import { getArrayComponents } from './encodeAbiParameters.js'
40
33
 
41
34
  export type DecodeAbiParametersReturnType<
42
- TParams extends
43
- | readonly AbiParameter[]
44
- | readonly unknown[] = readonly AbiParameter[],
35
+ TParams extends readonly AbiParameter[] = readonly AbiParameter[],
45
36
  > = AbiParametersToPrimitiveTypes<
46
37
  TParams extends readonly AbiParameter[] ? TParams : AbiParameter[]
47
38
  >
48
39
 
49
40
  export type DecodeAbiParametersErrorType =
50
- | AbiDecodingDataSizeTooSmallErrorType
51
- | AbiDecodingZeroDataErrorType
52
- | DecodeParamsErrorType
41
+ | HexToBytesErrorType
42
+ | BytesToHexErrorType
43
+ | DecodeParameterErrorType
53
44
  | SizeErrorType
54
45
  | ErrorType
55
46
 
56
47
  export function decodeAbiParameters<
57
- const TParams extends readonly AbiParameter[] | readonly unknown[],
58
- >(params: TParams, data: Hex): DecodeAbiParametersReturnType<TParams> {
59
- if (data === '0x' && (params as unknown[]).length > 0)
48
+ const TParams extends readonly AbiParameter[],
49
+ >(
50
+ params: TParams,
51
+ data: ByteArray | Hex,
52
+ ): DecodeAbiParametersReturnType<TParams> {
53
+ const bytes = typeof data === 'string' ? hexToBytes(data) : data
54
+ const cursor = createCursor(bytes)
55
+
56
+ if (size(bytes) === 0 && params.length > 0)
60
57
  throw new AbiDecodingZeroDataError()
61
58
  if (size(data) && size(data) < 32)
62
59
  throw new AbiDecodingDataSizeTooSmallError({
63
- data,
60
+ data: typeof data === 'string' ? data : bytesToHex(data),
64
61
  params: params as readonly AbiParameter[],
65
62
  size: size(data),
66
63
  })
67
- return decodeParams({
68
- data,
69
- params: params as readonly AbiParameter[],
70
- }) as unknown as DecodeAbiParametersReturnType<TParams>
71
- }
72
-
73
- ////////////////////////////////////////////////////////////////////
74
-
75
- type TupleAbiParameter = AbiParameter & { components: readonly AbiParameter[] }
76
-
77
- type DecodeParamsErrorType = DecodeParamErrorType | SizeErrorType | ErrorType
78
-
79
- function decodeParams<const TParams extends readonly AbiParameter[]>({
80
- data,
81
- params,
82
- }: { data: Hex; params: TParams }) {
83
- const decodedValues: unknown[] = []
84
- let position = 0
85
-
86
- for (let i = 0; i < params.length; i++) {
87
- if (position >= size(data))
88
- throw new AbiDecodingDataSizeTooSmallError({
89
- data,
90
- params,
91
- size: size(data),
92
- })
93
64
 
65
+ let consumed = 0
66
+ const values = []
67
+ for (let i = 0; i < params.length; ++i) {
94
68
  const param = params[i]
95
- const { consumed, value } = decodeParam({ data, param, position })
96
- decodedValues.push(value)
97
- // Step across the data by the amount of data consumed by this parameter.
98
- position += consumed
69
+ cursor.setPosition(consumed)
70
+ const [data, consumed_] = decodeParameter(cursor, param, {
71
+ staticPosition: 0,
72
+ })
73
+ consumed += consumed_
74
+ values.push(data)
99
75
  }
100
-
101
- return decodedValues as unknown as AbiParametersToPrimitiveTypes<TParams>
76
+ return values as DecodeAbiParametersReturnType<TParams>
102
77
  }
103
78
 
104
- type DecodeParamErrorType =
79
+ type DecodeParameterErrorType =
105
80
  | DecodeArrayErrorType
106
81
  | DecodeTupleErrorType
107
- | DecodeStringErrorType
108
- | DecodeBytesErrorType
109
- | DecodeNumberErrorType
110
82
  | DecodeAddressErrorType
111
83
  | DecodeBoolErrorType
84
+ | DecodeBytesErrorType
85
+ | DecodeNumberErrorType
86
+ | DecodeStringErrorType
112
87
  | InvalidAbiDecodingTypeErrorType
113
- | ErrorType
114
88
 
115
- function decodeParam({
116
- data,
117
- param,
118
- position,
119
- }: { data: Hex; param: AbiParameter; position: number }): {
120
- consumed: number
121
- value: any
122
- } {
89
+ function decodeParameter(
90
+ cursor: Cursor,
91
+ param: AbiParameter,
92
+ { staticPosition }: { staticPosition: number },
93
+ ) {
123
94
  const arrayComponents = getArrayComponents(param.type)
124
95
  if (arrayComponents) {
125
96
  const [length, type] = arrayComponents
126
- return decodeArray(data, {
127
- length,
128
- param: { ...param, type: type } as AbiParameter,
129
- position,
130
- })
131
- }
132
- if (param.type === 'tuple') {
133
- return decodeTuple(data, { param: param as TupleAbiParameter, position })
134
- }
135
- if (param.type === 'string') {
136
- return decodeString(data, { position })
137
- }
138
- if (param.type.startsWith('bytes')) {
139
- return decodeBytes(data, { param, position })
140
- }
141
-
142
- const value = slice(data, position, position + 32, { strict: true }) as Hex
143
- if (param.type.startsWith('uint') || param.type.startsWith('int')) {
144
- return decodeNumber(value, { param })
145
- }
146
- if (param.type === 'address') {
147
- return decodeAddress(value)
148
- }
149
- if (param.type === 'bool') {
150
- return decodeBool(value)
97
+ return decodeArray(cursor, { ...param, type }, { length, staticPosition })
151
98
  }
99
+ if (param.type === 'tuple')
100
+ return decodeTuple(cursor, param as TupleAbiParameter, { staticPosition })
101
+
102
+ if (param.type === 'address') return decodeAddress(cursor)
103
+ if (param.type === 'bool') return decodeBool(cursor)
104
+ if (param.type.startsWith('bytes'))
105
+ return decodeBytes(cursor, param, { staticPosition })
106
+ if (param.type.startsWith('uint') || param.type.startsWith('int'))
107
+ return decodeNumber(cursor, param)
108
+ if (param.type === 'string') return decodeString(cursor, { staticPosition })
152
109
  throw new InvalidAbiDecodingTypeError(param.type, {
153
110
  docsPath: '/docs/contract/decodeAbiParameters',
154
111
  })
155
112
  }
156
113
 
157
114
  ////////////////////////////////////////////////////////////////////
115
+ // Type Decoders
116
+
117
+ const sizeOfLength = 32
118
+ const sizeOfOffset = 32
158
119
 
159
120
  type DecodeAddressErrorType =
160
121
  | ChecksumAddressErrorType
161
- | SliceErrorType
122
+ | BytesToHexErrorType
123
+ | SliceBytesErrorType
162
124
  | ErrorType
163
125
 
164
- function decodeAddress(value: Hex) {
165
- return { consumed: 32, value: checksumAddress(slice(value, -20)) }
126
+ function decodeAddress(cursor: Cursor) {
127
+ const value = cursor.readBytes(32)
128
+ return [checksumAddress(bytesToHex(sliceBytes(value, -20))), 32]
166
129
  }
167
130
 
168
- type DecodeArrayErrorType = HexToNumberErrorType | SliceErrorType | ErrorType
169
-
170
- function decodeArray<const TParam extends AbiParameter>(
171
- data: Hex,
172
- {
173
- param,
174
- length,
175
- position,
176
- }: {
177
- param: TParam
178
- length: number | null
179
- position: number
180
- },
131
+ type DecodeArrayErrorType = BytesToNumberErrorType | ErrorType
132
+
133
+ function decodeArray(
134
+ cursor: Cursor,
135
+ param: AbiParameter,
136
+ { length, staticPosition }: { length: number | null; staticPosition: number },
181
137
  ) {
182
138
  // If the length of the array is not known in advance (dynamic array),
183
- // we will need to decode the offset of the array data.
139
+ // this means we will need to wonder off to the pointer and decode.
184
140
  if (!length) {
185
- // Get the offset of the array data.
186
- const offset = hexToNumber(
187
- slice(data, position, position + 32, { strict: true }),
188
- )
189
- if (offset < position)
190
- throw new AbiDecodingOffsetOutOfBoundsError({ offset, position })
141
+ // Dealing with a dynamic type, so get the offset of the array data.
142
+ const offset = bytesToNumber(cursor.readBytes(sizeOfOffset))
143
+
144
+ // Start is the static position of current slot + offset.
145
+ const start = staticPosition + offset
146
+ const startOfData = start + sizeOfLength
191
147
 
192
148
  // Get the length of the array from the offset.
193
- const length = hexToNumber(
194
- slice(data, offset, offset + 32, { strict: true }),
195
- )
149
+ cursor.setPosition(start)
150
+ const length = bytesToNumber(cursor.readBytes(sizeOfLength))
151
+
152
+ // Check if the array has any dynamic children.
153
+ const dynamicChild = hasDynamicChild(param)
196
154
 
197
155
  let consumed = 0
198
- const value: AbiParameterToPrimitiveType<TParam>[] = []
156
+ const value: unknown[] = []
199
157
  for (let i = 0; i < length; ++i) {
200
- const decodedChild = decodeParam({
201
- data: slice(data, offset + 32),
202
- param,
203
- position: consumed,
158
+ // If any of the children is dynamic, then all elements will be offset pointer, thus size of one slot (32 bytes).
159
+ // Otherwise, elements will be the size of their encoding (consumed bytes).
160
+ cursor.setPosition(startOfData + (dynamicChild ? i * 32 : consumed))
161
+ const [data, consumed_] = decodeParameter(cursor, param, {
162
+ staticPosition: startOfData,
204
163
  })
205
- consumed += decodedChild.consumed
206
- value.push(decodedChild.value)
164
+ consumed += consumed_
165
+ value.push(data)
207
166
  }
208
- return { value, consumed: 32 }
167
+
168
+ // As we have gone wondering, restore to the original position + next slot.
169
+ cursor.setPosition(staticPosition + 32)
170
+ return [value, 32]
209
171
  }
210
172
 
211
173
  // If the length of the array is known in advance,
212
174
  // and the length of an element deeply nested in the array is not known,
213
175
  // we need to decode the offset of the array data.
214
176
  if (hasDynamicChild(param)) {
215
- // Get the child type of the array.
216
- const arrayComponents = getArrayComponents(param.type)
217
- // If the child type is not known, the array is dynamic.
218
- const dynamicChild = !arrayComponents?.[0]
177
+ // Dealing with dynamic types, so get the offset of the array data.
178
+ const offset = bytesToNumber(cursor.readBytes(sizeOfOffset))
219
179
 
220
- let consumed = 0
221
- const value: AbiParameterToPrimitiveType<TParam>[] = []
180
+ // Start is the static position of current slot + offset.
181
+ const start = staticPosition + offset
182
+
183
+ const value: unknown[] = []
222
184
  for (let i = 0; i < length; ++i) {
223
- const offset = hexToNumber(
224
- slice(data, position, position + 32, { strict: true }),
225
- )
226
- const decodedChild = decodeParam({
227
- data: slice(data, offset),
228
- param,
229
- position: dynamicChild ? consumed : i * 32,
185
+ // Move cursor along to the next slot (next offset pointer).
186
+ cursor.setPosition(start + i * 32)
187
+ const [data] = decodeParameter(cursor, param, {
188
+ staticPosition: start,
230
189
  })
231
- consumed += decodedChild.consumed
232
- value.push(decodedChild.value)
190
+ value.push(data)
233
191
  }
234
- return { value, consumed: 32 }
192
+
193
+ // As we have gone wondering, restore to the original position + next slot.
194
+ cursor.setPosition(staticPosition + 32)
195
+ return [value, 32]
235
196
  }
236
197
 
237
- // If the length of the array is known in advance,
238
- // and the length of each element in the array is known,
239
- // the array data is encoded contiguously after the array.
198
+ // If the length of the array is known in advance and the array is deeply static,
199
+ // then we can just decode each element in sequence.
240
200
  let consumed = 0
241
- const value: AbiParameterToPrimitiveType<TParam>[] = []
201
+ const value: unknown[] = []
242
202
  for (let i = 0; i < length; ++i) {
243
- const decodedChild = decodeParam({
244
- data,
245
- param,
246
- position: position + consumed,
203
+ const [data, consumed_] = decodeParameter(cursor, param, {
204
+ staticPosition: staticPosition + consumed,
247
205
  })
248
- consumed += decodedChild.consumed
249
- value.push(decodedChild.value)
206
+ consumed += consumed_
207
+ value.push(data)
250
208
  }
251
- return { value, consumed }
209
+ return [value, consumed]
252
210
  }
253
211
 
254
- type DecodeBoolErrorType = HexToBoolErrorType | ErrorType
212
+ type DecodeBoolErrorType = BytesToBoolErrorType | ErrorType
255
213
 
256
- function decodeBool(value: Hex) {
257
- return { consumed: 32, value: hexToBool(value) }
214
+ function decodeBool(cursor: Cursor) {
215
+ return [bytesToBool(cursor.readBytes(32), { size: 32 }), 32]
258
216
  }
259
217
 
260
- type DecodeBytesErrorType = HexToNumberErrorType | SliceErrorType | ErrorType
218
+ type DecodeBytesErrorType =
219
+ | BytesToNumberErrorType
220
+ | BytesToHexErrorType
221
+ | ErrorType
261
222
 
262
- function decodeBytes<const TParam extends AbiParameter>(
263
- data: Hex,
264
- { param, position }: { param: TParam; position: number },
223
+ function decodeBytes(
224
+ cursor: Cursor,
225
+ param: AbiParameter,
226
+ { staticPosition }: { staticPosition: number },
265
227
  ) {
266
228
  const [_, size] = param.type.split('bytes')
267
229
  if (!size) {
268
- // If we don't have a size, we're dealing with a dynamic-size array
269
- // so we need to read the offset of the data part first.
270
- const offset = hexToNumber(
271
- slice(data, position, position + 32, { strict: true }),
272
- )
273
- const length = hexToNumber(
274
- slice(data, offset, offset + 32, { strict: true }),
275
- )
230
+ // Dealing with dynamic types, so get the offset of the bytes data.
231
+ const offset = bytesToNumber(cursor.readBytes(32))
232
+
233
+ // Set position of the cursor to start of bytes data.
234
+ cursor.setPosition(staticPosition + offset)
235
+
236
+ const length = bytesToNumber(cursor.readBytes(32))
237
+
276
238
  // If there is no length, we have zero data.
277
- if (length === 0) return { consumed: 32, value: '0x' }
278
- const value = slice(data, offset + 32, offset + 32 + length, {
279
- strict: true,
280
- })
281
- return { consumed: 32, value }
239
+ if (length === 0) {
240
+ // As we have gone wondering, restore to the original position + next slot.
241
+ cursor.setPosition(staticPosition + 32)
242
+ return ['0x', 32]
243
+ }
244
+
245
+ const data = cursor.readBytes(length)
246
+
247
+ // As we have gone wondering, restore to the original position + next slot.
248
+ cursor.setPosition(staticPosition + 32)
249
+ return [bytesToHex(data), 32]
282
250
  }
283
251
 
284
- const value = slice(data, position, position + parseInt(size), {
285
- strict: true,
286
- })
287
- return { consumed: 32, value }
252
+ const value = bytesToHex(cursor.readBytes(parseInt(size), 32))
253
+ return [value, 32]
288
254
  }
289
255
 
290
256
  type DecodeNumberErrorType =
291
- | HexToBigIntErrorType
292
- | HexToNumberErrorType
257
+ | BytesToNumberErrorType
258
+ | BytesToBigIntErrorType
293
259
  | ErrorType
294
260
 
295
- function decodeNumber<const TParam extends AbiParameter>(
296
- value: Hex,
297
- { param }: { param: TParam },
298
- ) {
261
+ function decodeNumber(cursor: Cursor, param: AbiParameter) {
299
262
  const signed = param.type.startsWith('int')
300
263
  const size = parseInt(param.type.split('int')[1] || '256')
301
- return {
302
- consumed: 32,
303
- value:
304
- size > 48
305
- ? hexToBigInt(value, { signed })
306
- : hexToNumber(value, { signed }),
307
- }
264
+ const value = cursor.readBytes(32)
265
+ return [
266
+ size > 48
267
+ ? bytesToBigInt(value, { signed })
268
+ : bytesToNumber(value, { signed }),
269
+ 32,
270
+ ]
308
271
  }
309
272
 
310
- type DecodeStringErrorType =
311
- | HexToNumberErrorType
312
- | HexToStringErrorType
313
- | SliceErrorType
314
- | TrimErrorType
315
- | ErrorType
273
+ type TupleAbiParameter = AbiParameter & { components: readonly AbiParameter[] }
316
274
 
317
- function decodeString(data: Hex, { position }: { position: number }) {
318
- const offset = hexToNumber(
319
- slice(data, position, position + 32, { strict: true }),
320
- )
321
- const length = hexToNumber(slice(data, offset, offset + 32, { strict: true }))
322
- // If there is no length, we have zero data (empty string).
323
- if (length === 0) return { consumed: 32, value: '' }
324
- const value = hexToString(
325
- trim(slice(data, offset + 32, offset + 32 + length, { strict: true })),
326
- )
327
- return { consumed: 32, value }
328
- }
275
+ type DecodeTupleErrorType = BytesToNumberErrorType | ErrorType
329
276
 
330
- type DecodeTupleErrorType =
331
- | HasDynamicChildErrorType
332
- | HexToNumberErrorType
333
- | SliceErrorType
334
- | ErrorType
335
-
336
- function decodeTuple<
337
- const TParam extends AbiParameter & { components: readonly AbiParameter[] },
338
- >(data: Hex, { param, position }: { param: TParam; position: number }) {
277
+ function decodeTuple(
278
+ cursor: Cursor,
279
+ param: TupleAbiParameter,
280
+ { staticPosition }: { staticPosition: number },
281
+ ) {
339
282
  // Tuples can have unnamed components (i.e. they are arrays), so we must
340
283
  // determine whether the tuple is named or unnamed. In the case of a named
341
284
  // tuple, the value will be an object where each property is the name of the
@@ -351,39 +294,73 @@ function decodeTuple<
351
294
  // If the tuple has a dynamic child, we must first decode the offset to the
352
295
  // tuple data.
353
296
  if (hasDynamicChild(param)) {
354
- const offset = hexToNumber(
355
- slice(data, position, position + 32, { strict: true }),
356
- )
357
- // Decode each component of the tuple, starting at the offset.
297
+ // Dealing with dynamic types, so get the offset of the tuple data.
298
+ const offset = bytesToNumber(cursor.readBytes(sizeOfOffset))
299
+
300
+ // Start is the static position of referencing slot + offset.
301
+ const start = staticPosition + offset
302
+
358
303
  for (let i = 0; i < param.components.length; ++i) {
359
304
  const component = param.components[i]
360
- const decodedChild = decodeParam({
361
- data: slice(data, offset),
362
- param: component,
363
- position: consumed,
305
+ cursor.setPosition(start + consumed)
306
+ const [data, consumed_] = decodeParameter(cursor, component, {
307
+ staticPosition: start,
364
308
  })
365
- consumed += decodedChild.consumed
366
- value[hasUnnamedChild ? i : component?.name!] = decodedChild.value
309
+ consumed += consumed_
310
+ value[hasUnnamedChild ? i : component?.name!] = data
367
311
  }
368
- return { consumed: 32, value }
312
+
313
+ // As we have gone wondering, restore to the original position + next slot.
314
+ cursor.setPosition(staticPosition + 32)
315
+ return [value, 32]
369
316
  }
370
317
 
371
318
  // If the tuple has static children, we can just decode each component
372
319
  // in sequence.
373
320
  for (let i = 0; i < param.components.length; ++i) {
374
321
  const component = param.components[i]
375
- const decodedChild = decodeParam({
376
- data,
377
- param: component,
378
- position: position + consumed,
322
+ const [data, consumed_] = decodeParameter(cursor, component, {
323
+ staticPosition,
379
324
  })
380
- consumed += decodedChild.consumed
381
- value[hasUnnamedChild ? i : component?.name!] = decodedChild.value
325
+ value[hasUnnamedChild ? i : component?.name!] = data
326
+ consumed += consumed_
382
327
  }
383
- return { consumed, value }
328
+ return [value, consumed]
384
329
  }
385
330
 
386
- type HasDynamicChildErrorType = GetArrayComponentsErrorType | ErrorType
331
+ type DecodeStringErrorType =
332
+ | BytesToNumberErrorType
333
+ | BytesToStringErrorType
334
+ | TrimErrorType
335
+ | ErrorType
336
+
337
+ function decodeString(
338
+ cursor: Cursor,
339
+ { staticPosition }: { staticPosition: number },
340
+ ) {
341
+ // Get offset to start of string data.
342
+ const offset = bytesToNumber(cursor.readBytes(32))
343
+
344
+ // Start is the static position of current slot + offset.
345
+ const start = staticPosition + offset
346
+ cursor.setPosition(start)
347
+
348
+ const length = bytesToNumber(cursor.readBytes(32))
349
+
350
+ // If there is no length, we have zero data (empty string).
351
+ if (length === 0) {
352
+ cursor.setPosition(staticPosition + 32)
353
+ return ['', 32]
354
+ }
355
+
356
+ const data = cursor.readBytes(length, 32)
357
+ const value = bytesToString(trim(data))
358
+
359
+ // As we have gone wondering, restore to the original position + next slot.
360
+ cursor.setPosition(staticPosition + 32)
361
+
362
+ return [value, 32]
363
+ }
387
364
 
388
365
  function hasDynamicChild(param: AbiParameter) {
389
366
  const { type } = param
@@ -24,11 +24,13 @@ import type {
24
24
  Prettify,
25
25
  UnionEvaluate,
26
26
  } from '../../types/utils.js'
27
+ import { size } from '../data/size.js'
27
28
  import {
28
29
  type GetEventSelectorErrorType,
29
30
  getEventSelector,
30
31
  } from '../hash/getEventSelector.js'
31
32
 
33
+ import { PositionOutOfBoundsError } from '../../errors/cursor.js'
32
34
  import {
33
35
  type DecodeAbiParametersErrorType,
34
36
  decodeAbiParameters,
@@ -156,12 +158,15 @@ export function decodeEventLog<
156
158
  }
157
159
  } catch (err) {
158
160
  if (strict) {
159
- if (err instanceof AbiDecodingDataSizeTooSmallError)
161
+ if (
162
+ err instanceof AbiDecodingDataSizeTooSmallError ||
163
+ err instanceof PositionOutOfBoundsError
164
+ )
160
165
  throw new DecodeLogDataMismatch({
161
166
  abiItem,
162
- data: err.data,
163
- params: err.params,
164
- size: err.size,
167
+ data: data,
168
+ params: nonIndexedInputs,
169
+ size: size(data),
165
170
  })
166
171
  throw err
167
172
  }