Skip to content

Commit

Permalink
getRecords safety check tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
TateB committed Jan 4, 2024
1 parent 66caae7 commit 6d34c20
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 50 deletions.
48 changes: 47 additions & 1 deletion packages/ensjs/src/functions/public/getRecords.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createPublicClient, http } from 'viem'
import { RawContractError, createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { addEnsContracts } from '../../index.js'
import {
Expand Down Expand Up @@ -98,4 +98,50 @@ describe('getRecords()', () => {
}
`)
})

it('returns null results when known resolver error', async () => {
await expect(
getRecords.decode(
publicClient,
new RawContractError({
data: '0x7199966d', // ResolverNotFound()
}),
[{ type: 'coin', key: 60, call: { to: '0x1234', data: '0x5678' } }],
{ name: 'test.eth' },
),
).resolves.toMatchInlineSnapshot(`
{
"coins": [],
"resolverAddress": "0x0000000000000000000000000000000000000000",
}
`)
})

it('throws when unknown resolver error', async () => {
await expect(
getRecords.decode(
publicClient,
new RawContractError({
data: '0x4ced43fb', // SwagError()
}),
[{ type: 'coin', key: 60, call: { to: '0x1234', data: '0x5678' } }],
{ name: 'test.eth' },
),
).rejects.toThrowErrorMatchingInlineSnapshot(`
"The contract function "resolve" reverted with the following signature:
0x4ced43fb
Unable to decode signature "0x4ced43fb" as it was not found on the provided ABI.
Make sure you are using the correct ABI and that the error exists on it.
You can look up the decoded signature here: https://openchain.xyz/signatures?query=0x4ced43fb.
Contract Call:
address: ${deploymentAddresses.UniversalResolver}
function: resolve(bytes name, bytes[] data)
args: (0x04746573740365746800, ["0x5678"])
Docs: https://viem.sh/docs/contract/decodeErrorResult.html
Version: [email protected]"
`)
})
})
83 changes: 36 additions & 47 deletions packages/ensjs/src/functions/public/getRecords.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import {
BaseError,
decodeAbiParameters,
decodeErrorResult,
decodeFunctionResult,
encodeFunctionData,
getContractError,
hexToBigInt,
toHex,
type Address,
Expand All @@ -19,9 +17,9 @@ import type {
SimpleTransactionRequest,
TransactionRequestWithPassthrough,
} from '../../types.js'
import { checkSafeUniversalResolverData } from '../../utils/checkSafeUniversalResolverData.js'
import { EMPTY_ADDRESS } from '../../utils/consts.js'
import { generateFunction } from '../../utils/generateFunction.js'
import { getRevertErrorData } from '../../utils/getRevertErrorData.js'
import { packetToBytes } from '../../utils/hexEncodedName.js'
import _getAbi, { type InternalGetAbiReturnType } from './_getAbi.js'
import _getAddr from './_getAddr.js'
Expand Down Expand Up @@ -206,50 +204,41 @@ const decode = async <TParams extends GetRecordsParameters>(
resolverAddress = resolver.address
recordData = result.map((r) => r.returnData)
} else {
if (typeof data === 'object') {
const errorData = getRevertErrorData(data)
if (errorData) {
const decodedError = decodeErrorResult({
abi: universalResolverResolveArraySnippet,
data: errorData,
})
if (
decodedError.errorName === 'ResolverNotFound' ||
decodedError.errorName === 'ResolverWildcardNotSupported'
)
return passthrough.reduce(
(prev, curr) => {
if (!curr) return prev
if (curr.type === 'coin' && !('coin' in prev)) {
return { ...prev, coins: [] }
}
if (curr.type === 'text' && !('texts' in prev)) {
return { ...prev, texts: [] }
}
if (curr.type === 'contentHash' && !('contentHash' in prev)) {
return { ...prev, contentHash: null }
}
// abi
return { ...prev, abi: null }
},
{
resolverAddress: EMPTY_ADDRESS,
} as unknown as GetRecordsReturnType<TParams>,
)
}
throw getContractError(data, {
abi: universalResolverResolveArraySnippet,
functionName: 'resolve',
args: [
toHex(packetToBytes(name)),
calls.filter((c) => c).map((c) => c!.call.data),
],
address: getChainContractAddress({
client,
contract: 'ensUniversalResolver',
}),
}) as BaseError
}
const isSafe = checkSafeUniversalResolverData(data, {
strict: false,
abi: universalResolverResolveArraySnippet,
args: () => [
toHex(packetToBytes(name)),
calls.filter((c) => c).map((c) => c!.call.data),
],
functionName: 'resolve',
address: getChainContractAddress({
client,
contract: 'ensUniversalResolver',
}),
})

if (!isSafe)
return passthrough.reduce(
(prev, curr) => {
if (!curr) return prev
if (curr.type === 'coin' && !('coin' in prev)) {
return { ...prev, coins: [] }
}
if (curr.type === 'text' && !('texts' in prev)) {
return { ...prev, texts: [] }
}
if (curr.type === 'contentHash' && !('contentHash' in prev)) {
return { ...prev, contentHash: null }
}
// abi
return { ...prev, abi: null }
},
{
resolverAddress: EMPTY_ADDRESS,
} as unknown as GetRecordsReturnType<TParams>,
)

const result = decodeFunctionResult({
abi: universalResolverResolveArraySnippet,
functionName: 'resolve',
Expand Down
28 changes: 28 additions & 0 deletions packages/ensjs/src/utils/checkSafeUniversalResolverData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,34 @@ describe('checkSafeUniversalResolverData', () => {
`)
})

it('throws error with args as a function', () => {
expect(() => {
checkSafeUniversalResolverData(
new RawContractError({
data: '0x7199966d', // ResolverNotFound()
}),
{
strict: true,
abi: universalResolverResolveSnippet,
args: () => ['ab', 'cd'],
functionName: 'resolve',
address: '0x1234567890abcdef',
},
)
}).toThrowErrorMatchingInlineSnapshot(`
"The contract function "resolve" reverted.
Error: ResolverNotFound()
Contract Call:
address: 0x1234567890abcdef
function: resolve(bytes name, bytes data)
args: (ab, cd)
Version: [email protected]"
`)
})

it('throws error when the data is an unknown error and strict is false', () => {
expect(() => {
checkSafeUniversalResolverData(
Expand Down
5 changes: 3 additions & 2 deletions packages/ensjs/src/utils/checkSafeUniversalResolverData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { getRevertErrorData } from './getRevertErrorData.js'
type CheckSafeUniversalResolverDataParameters = Prettify<
{
strict: boolean | undefined
} & Parameters<typeof getContractError>[1]
args: any[] | (() => any[])
} & Omit<Parameters<typeof getContractError>[1], 'args'>
>

/**
Expand Down Expand Up @@ -48,7 +49,7 @@ export const checkSafeUniversalResolverData = (
}
throw getContractError(data, {
abi,
args,
args: typeof args === 'function' ? args() : args,
functionName,
address,
docsPath,
Expand Down

0 comments on commit 6d34c20

Please sign in to comment.