-
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🐛 fix: eth get_logs not handling hex numbers (#1428)
## Description _Concise description of proposed changes_ ## Testing Explain the quality checks that have been done on the code changes ## Additional Information - [ ] I read the [contributing docs](../docs/contributing.md) (if this is your first contribution) Your ENS/address: --------- Co-authored-by: William Cory <[email protected]>
- Loading branch information
1 parent
989a334
commit bc00e14
Showing
5 changed files
with
151 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@tevm/actions": patch | ||
--- | ||
|
||
Fixed bug in eth_getLogs not handling nubmer hex |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@tevm/actions": patch | ||
--- | ||
|
||
Fixed bug with eth_getLogs not handling numbered hex string logs well |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { InvalidBlockError } from '@tevm/errors' | ||
import { hexToBigInt, hexToBytes } from '@tevm/utils' | ||
|
||
/** | ||
* @param {import('@tevm/blockchain').Chain} blockchain | ||
* @param {import('../../common/BlockParam.js').BlockParam} blockParam | ||
* @returns {Promise<bigint >} | ||
*/ | ||
export const parseBlockParam = async (blockchain, blockParam) => { | ||
if (typeof blockParam === 'number') { | ||
return BigInt(blockParam) | ||
} | ||
if (typeof blockParam === 'bigint') { | ||
return blockParam | ||
} | ||
if (typeof blockParam === 'string' && blockParam.startsWith('0x')) { | ||
if (blockParam.length === 66) { | ||
const block = await blockchain.getBlock(hexToBytes(/** @type {import('@tevm/utils').Hex}*/ (blockParam))) | ||
return BigInt(block.header.number) | ||
} | ||
return hexToBigInt(/** @type {import('@tevm/utils').Hex}*/ (blockParam)) | ||
} | ||
if (blockParam === 'safe') { | ||
const safeBlock = blockchain.blocksByTag.get('safe') | ||
// let's handle it here in case we forget to update it later | ||
if (safeBlock) { | ||
return safeBlock.header.number | ||
} | ||
throw new InvalidBlockError('safe not currently supported as block tag') | ||
} | ||
if (blockParam === 'latest' || blockParam === undefined) { | ||
const safeBlock = blockchain.blocksByTag.get('latest') | ||
// let's handle it here in case we forget to update it later | ||
if (safeBlock) { | ||
return safeBlock.header.number | ||
} | ||
throw new InvalidBlockError('latest block does not exist on chain') | ||
} | ||
if (blockParam === 'pending') { | ||
// for pending we need to mine a new block and then handle it | ||
// let's skip this functionality for now | ||
throw new InvalidBlockError( | ||
'Pending not yet supported but will be in future. Consider opening an issue or reaching out on telegram if you need this feature to expediate its release', | ||
) | ||
} | ||
if (blockParam === 'earliest') { | ||
return BigInt(1) | ||
} | ||
if (blockParam === 'finalized') { | ||
throw new InvalidBlockError('finalized noet yet supported for this feature') | ||
} | ||
blockchain.logger.error({ blockParam }, 'Unknown block param pased to blockNumberHandler') | ||
throw new InvalidBlockError(`Unknown block param ${blockParam} pased to blockNumberHandler`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { InvalidBlockError } from '@tevm/errors' | ||
import { beforeEach, describe, expect, it, vi } from 'vitest' | ||
import { parseBlockParam } from './parseBlockParam.js' | ||
|
||
describe('parseBlockParam', () => { | ||
let mockBlockchain: any | ||
|
||
beforeEach(() => { | ||
mockBlockchain = { | ||
getBlock: vi.fn(), | ||
blocksByTag: new Map(), | ||
logger: { | ||
error: vi.fn(), | ||
}, | ||
} | ||
}) | ||
|
||
it('should handle number input', async () => { | ||
const result = await parseBlockParam(mockBlockchain, 123 as any) | ||
expect(result).toBe(123n) | ||
}) | ||
|
||
it('should handle bigint input', async () => { | ||
const result = await parseBlockParam(mockBlockchain, 456n) | ||
expect(result).toBe(456n) | ||
}) | ||
|
||
it('should handle hex block number', async () => { | ||
mockBlockchain.getBlock.mockResolvedValue({ header: { number: 789 } }) | ||
const hash = `0x${'12'.repeat(32)}` as const | ||
const result = await parseBlockParam(mockBlockchain, hash) | ||
expect(result).toBe(789n) | ||
}) | ||
|
||
it('should handle hex string block number input', async () => { | ||
mockBlockchain.getBlock.mockResolvedValue({ header: { number: 789 } }) | ||
const result = await parseBlockParam(mockBlockchain, '0x123') | ||
expect(result).toBe(291n) | ||
}) | ||
|
||
it('should handle "safe" tag', async () => { | ||
mockBlockchain.blocksByTag.set('safe', { header: { number: 101n } }) | ||
const result = await parseBlockParam(mockBlockchain, 'safe') | ||
expect(result).toBe(101n) | ||
}) | ||
|
||
it('should throw error for unsupported "safe" tag', async () => { | ||
await expect(parseBlockParam(mockBlockchain, 'safe')).rejects.toThrow(InvalidBlockError) | ||
}) | ||
|
||
it('should handle "latest" tag', async () => { | ||
mockBlockchain.blocksByTag.set('latest', { header: { number: 202n } }) | ||
const result = await parseBlockParam(mockBlockchain, 'latest') | ||
expect(result).toBe(202n) | ||
}) | ||
|
||
it('should handle undefined as "latest"', async () => { | ||
mockBlockchain.blocksByTag.set('latest', { header: { number: 303n } }) | ||
const result = await parseBlockParam(mockBlockchain, undefined as any) | ||
expect(result).toBe(303n) | ||
}) | ||
|
||
it('should throw error for missing "latest" block', async () => { | ||
await expect(parseBlockParam(mockBlockchain, 'latest')).rejects.toThrow(InvalidBlockError) | ||
}) | ||
|
||
it('should throw error for "pending" tag', async () => { | ||
await expect(parseBlockParam(mockBlockchain, 'pending')).rejects.toThrow(InvalidBlockError) | ||
}) | ||
|
||
it('should handle "earliest" tag', async () => { | ||
const result = await parseBlockParam(mockBlockchain, 'earliest') | ||
expect(result).toBe(1n) | ||
}) | ||
|
||
it('should throw error for "finalized" tag', async () => { | ||
await expect(parseBlockParam(mockBlockchain, 'finalized')).rejects.toThrow(InvalidBlockError) | ||
}) | ||
|
||
it('should throw error for unknown block param', async () => { | ||
await expect(parseBlockParam(mockBlockchain, 'unknown' as any)).rejects.toThrow(InvalidBlockError) | ||
expect(mockBlockchain.logger.error).toHaveBeenCalled() | ||
}) | ||
}) |