Skip to content

Commit

Permalink
fix: parse abi item fallback parsing (#261)
Browse files Browse the repository at this point in the history
* fix: parse abi item fallback parsing

* ci: apply automated fixes

* refactor: extract parse signature functions, and test them

* chore: tweaks

* chore: tweaks

* Update .changeset/red-turtles-refuse.md

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Tom Meagher <[email protected]>
  • Loading branch information
3 people authored Dec 21, 2024
1 parent eed89ed commit 889e85d
Show file tree
Hide file tree
Showing 10 changed files with 307 additions and 92 deletions.
5 changes: 5 additions & 0 deletions .changeset/red-turtles-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"abitype": patch
---

Fixed `parseAbiItem` fallback signature parsing
2 changes: 1 addition & 1 deletion .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
timeout-minutes: 5
strategy:
matrix:
version: ['5.0.4', '5.1.6', '5.2.2', '5.3.3', '5.4.5', '5.5.2', 'latest']
version: ['5.0.4', '5.1.6', '5.2.2', '5.3.3', '5.4.5', '5.5.2', '5.6', 'latest']

steps:
- name: Clone repository
Expand Down
68 changes: 68 additions & 0 deletions packages/abitype/src/human-readable/integration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { expect, test } from 'vitest'
import { formatAbiItem } from './formatAbiItem.js'
import { parseAbiItem } from './parseAbiItem.js'

test.each([
{
type: 'fallback',
stateMutability: 'payable',
} as const,
{
type: 'fallback',
stateMutability: 'nonpayable',
} as const,
{
type: 'receive',
stateMutability: 'payable',
} as const,
{
type: 'function',
name: 'foo',
inputs: [{ type: 'string' }],
outputs: [],
stateMutability: 'nonpayable',
} as const,
{
type: 'event',
name: 'Foo',
inputs: [
{ type: 'address', name: 'from', indexed: true },
{ type: 'address', name: 'to', indexed: true },
{ type: 'uint256', name: 'amount' },
],
} as const,
{
type: 'constructor',
stateMutability: 'nonpayable',
inputs: [{ type: 'string' }],
} as const,
{
type: 'constructor',
stateMutability: 'payable',
inputs: [{ type: 'string' }],
} as const,
{
type: 'function',
name: 'initWormhole',
inputs: [
{
type: 'tuple[]',
name: 'configs',
components: [
{
type: 'uint256',
name: 'chainId',
},
{
type: 'uint16',
name: 'wormholeChainId',
},
],
},
],
outputs: [],
stateMutability: 'nonpayable',
} as const,
])('use of parseAbiItem - formatAbiItem should be reversible', (abiItem) => {
expect(parseAbiItem(formatAbiItem(abiItem))).toEqual(abiItem)
})
16 changes: 16 additions & 0 deletions packages/abitype/src/human-readable/parseAbiItem.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,22 @@ test('parseAbiItem', () => {

const signature: string = 'function foo()'
expectTypeOf(parseAbiItem(signature)).toEqualTypeOf<Abi[number]>()

// fallback
expectTypeOf(parseAbiItem('fallback() external')).toEqualTypeOf<{
readonly type: 'fallback'
readonly stateMutability: 'nonpayable'
}>()
expectTypeOf(parseAbiItem('fallback() external payable')).toEqualTypeOf<{
readonly type: 'fallback'
readonly stateMutability: 'payable'
}>()

// receive
expectTypeOf(parseAbiItem('receive() external payable')).toEqualTypeOf<{
readonly type: 'receive'
readonly stateMutability: 'payable'
}>()
})

test('nested tuples', () => {
Expand Down
8 changes: 8 additions & 0 deletions packages/abitype/src/human-readable/parseAbiItem.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ test.each([
signature: ['fallback() external'],
expected: {
type: 'fallback',
stateMutability: 'nonpayable',
},
},
{
signature: ['fallback() external payable'],
expected: {
type: 'fallback',
stateMutability: 'payable',
},
},
])('parseAbiItem($signature)', ({ signature, expected }) => {
Expand Down
6 changes: 6 additions & 0 deletions packages/abitype/src/human-readable/runtime/signatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ const fallbackSignatureRegex =
export function isFallbackSignature(signature: string) {
return fallbackSignatureRegex.test(signature)
}
export function execFallbackSignature(signature: string) {
return execTyped<{
parameters: string
stateMutability?: Extract<AbiStateMutability, 'payable'>
}>(fallbackSignatureRegex, signature)
}

// https://regexr.com/78u1k
const receiveSignatureRegex = /^receive\(\) external payable$/
Expand Down
69 changes: 66 additions & 3 deletions packages/abitype/src/human-readable/runtime/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import {
isSolidityType,
isValidDataLocation,
parseAbiParameter,
parseConstructorSignature,
parseErrorSignature,
parseEventSignature,
parseFallbackSignature,
parseFunctionSignature,
parseSignature,
splitParameters,
} from './utils.js'
Expand Down Expand Up @@ -93,6 +98,20 @@ test.each([
stateMutability: 'payable',
},
},
{
signature: 'fallback() external payable',
expected: {
type: 'fallback',
stateMutability: 'payable',
},
},
{
signature: 'fallback() external',
expected: {
type: 'fallback',
stateMutability: 'nonpayable',
},
},
])('parseSignature($signature)', ({ signature, expected }) => {
expect(parseSignature(signature)).toEqual(expected)
})
Expand Down Expand Up @@ -154,12 +173,56 @@ test('invalid signature', () => {
)

expect(() =>
parseSignature('method foo_(string)'),
parseFunctionSignature('function foo() invalid'),
).toThrowErrorMatchingInlineSnapshot(
`
[UnknownSignatureError: Unknown signature.
[InvalidSignatureError: Invalid function signature.
Details: function foo() invalid
Version: [email protected]]
`,
)

expect(() =>
parseEventSignature('event Foo(string memory foo) invalid'),
).toThrowErrorMatchingInlineSnapshot(
`
[InvalidSignatureError: Invalid event signature.
Details: event Foo(string memory foo) invalid
Version: [email protected]]
`,
)

expect(() => {
parseErrorSignature('error Foo(string memory foo) invalid')
}).toThrowErrorMatchingInlineSnapshot(
`
[InvalidSignatureError: Invalid error signature.
Details: error Foo(string memory foo) invalid
Version: [email protected]]
`,
)

expect(() => {
parseConstructorSignature('constructor() invalid')
}).toThrowErrorMatchingInlineSnapshot(
`
[InvalidSignatureError: Invalid constructor signature.
Details: constructor() invalid
Version: [email protected]]
`,
)

expect(() => {
parseFallbackSignature('fallback() external invalid')
}).toThrowErrorMatchingInlineSnapshot(
`
[InvalidSignatureError: Invalid fallback signature.
Details: method foo_(string)
Details: fallback() external invalid
Version: [email protected]]
`,
)
Expand Down
Loading

0 comments on commit 889e85d

Please sign in to comment.