diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a57bab8..9b0e8a3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,8 +29,9 @@ jobs: - name: Test with Jest run: | export PROVIDER_URI=${{ secrets.PROVIDER_URI }} - export PROVIDER_URI_GOERLI=${{ secrets.PROVIDER_URI_GOERLI }} export PROVIDER_URI_SEPOLIA=${{ secrets.PROVIDER_URI_SEPOLIA }} + export PROVIDER_URI_10=${{ secrets.PROVIDER_URI_10 }} + export PROVIDER_URI_8453=${{ secrets.PROVIDER_URI_8453 }} export PINATA_JWT=${{ secrets.PINATA_JWT }} export QUICKNODE_API_KEY=${{ secrets.QUICKNODE_API_KEY }} export QUICKNODE_IPFS_URL=${{ secrets.QUICKNODE_IPFS_URL }} diff --git a/package.json b/package.json index 4ea1aec..cb461f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@axiom-crypto/tools", - "version": "2.1.0", + "version": "2.1.1", "description": "Useful data, field, and byte manipulation tools for Axiom.", "author": "Intrinsic Technologies", "license": "MIT", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b44c870..b2684f8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1091,7 +1091,7 @@ packages: /axios@1.6.7: resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==} dependencies: - follow-redirects: 1.15.5 + follow-redirects: 1.15.6 form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -1619,8 +1619,8 @@ packages: path-exists: 4.0.0 dev: true - /follow-redirects@1.15.5: - resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} + /follow-redirects@1.15.6: + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} engines: {node: '>=4.0'} peerDependencies: debug: '*' diff --git a/src/codec/v2/types.ts b/src/codec/v2/types.ts index ae71f37..3000cf3 100644 --- a/src/codec/v2/types.ts +++ b/src/codec/v2/types.ts @@ -60,7 +60,13 @@ export interface AxiomV2Result { computeResultsHash: string; } -export interface Subquery {} +export interface Subquery { + /** + * The block number of the block that the subquery needs data from. + * `undefined` if no block is needed. + */ + blockNumber?: number; +} export interface StorageSubqueryV1 extends Subquery { blockNumber: number; @@ -190,8 +196,9 @@ export enum ReceiptField { } export enum TxType { - Legacy, - Eip2930, - Eip1559, - Eip4844, + Legacy = 0, + Eip2930 = 1, + Eip1559 = 2, + Eip4844 = 3, + OpSystem = 126, // 0x7E } diff --git a/src/rpc/subqueryField.ts b/src/rpc/subqueryField.ts index a587073..05d4d4b 100644 --- a/src/rpc/subqueryField.ts +++ b/src/rpc/subqueryField.ts @@ -369,6 +369,9 @@ export async function getTxFieldValue( if (type === TxType.Eip4844) { logger.error(`EIP-4844 transactions are not yet supported`); return null; + } else if (type === TxType.OpSystem) { + logger.error(`OP stack System transactions are not yet supported`); + return null; } const value = getValue(tx, type); @@ -487,6 +490,9 @@ export async function getReceiptFieldValue( if (Number(receipt?.type) === TxType.Eip4844) { logger.error(`EIP-4844 transaction receipts are not yet supported`); return null; + } else if (Number(receipt?.type) === TxType.OpSystem) { + logger.error(`OP stack System transaction receipts are not yet supported`); + return null; } const value = getValue(receipt); diff --git a/src/utils/gasCalc.ts b/src/utils/gasCalc.ts new file mode 100644 index 0000000..033e018 --- /dev/null +++ b/src/utils/gasCalc.ts @@ -0,0 +1,16 @@ +import { ByteStringReader } from "./byteStringReader"; + +export function calculateCalldataGas(hexString: string): number { + let gas = 0; + const reader = new ByteStringReader(hexString); + while (reader.getNumBytesRemaining() > 0) { + const byte = reader.readBytes(1); + if (byte === "0x00") { + gas += 4; + } else { + gas += 16; + } + } + + return gas; +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 6fd57d5..f428f5e 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -4,3 +4,4 @@ export * from "./storage"; export * from "./byteStringReader"; export * from "./evm"; export * from "./rlp"; +export * from "./gasCalc"; \ No newline at end of file diff --git a/test/codec/v2/data/codecData.ts b/test/codec/v2/data/codecData.ts index b95103a..4a516dd 100644 --- a/test/codec/v2/data/codecData.ts +++ b/test/codec/v2/data/codecData.ts @@ -11,6 +11,12 @@ import { AxiomV2DataQuery, bytes32, AxiomV2FeeData, + HeaderSubquery, + AccountSubquery, + StorageSubquery, + TxSubquery, + ReceiptSubquery, + SolidityNestedMappingSubquery, } from "../../../../src"; @@ -88,14 +94,14 @@ export const dataSubqueries: DataSubquery[] = [ subqueryData: { blockNumber: BLOCK_NUMBER, fieldIdx: HeaderField.Miner, - }, + } as HeaderSubquery, }, { type: DataSubqueryType.Header, subqueryData: { blockNumber: BLOCK_NUMBER + 1, fieldIdx: HeaderField.GasLimit, - }, + } as HeaderSubquery, }, { type: DataSubqueryType.Account, @@ -103,7 +109,7 @@ export const dataSubqueries: DataSubquery[] = [ blockNumber: BLOCK_NUMBER, addr: WETH_ADDR, fieldIdx: AccountField.CodeHash, - }, + } as AccountSubquery, }, { type: DataSubqueryType.Storage, @@ -111,7 +117,7 @@ export const dataSubqueries: DataSubquery[] = [ blockNumber: BLOCK_NUMBER, addr: WETH_ADDR, slot: bytes32(1), - }, + } as StorageSubquery, }, { type: DataSubqueryType.Transaction, @@ -119,7 +125,7 @@ export const dataSubqueries: DataSubquery[] = [ blockNumber: 15060942, txIdx: 114, fieldOrCalldataIdx: TxField.To, - }, + } as TxSubquery, }, { type: DataSubqueryType.Receipt, @@ -129,7 +135,7 @@ export const dataSubqueries: DataSubquery[] = [ fieldOrLogIdx: 0, topicOrDataOrAddressIdx: 0, eventSchema: "0x255910aca2752f3c05fcb4a54d3d8d93bb809a9c8cc215d5eed2504d44cbd865", - }, + } as ReceiptSubquery, }, { type: DataSubqueryType.SolidityNestedMapping, @@ -139,7 +145,7 @@ export const dataSubqueries: DataSubquery[] = [ mappingSlot: bytes32(5), mappingDepth: 3, keys: [bytes32(WETH_ADDR), bytes32(WSOL_ADDR), bytes32(10000)], - }, + } as SolidityNestedMappingSubquery, }, ]; export const dataQuery: AxiomV2DataQuery = { diff --git a/test/codec/v2/encode.test.ts b/test/codec/v2/encode.test.ts index b252e90..92f5be1 100644 --- a/test/codec/v2/encode.test.ts +++ b/test/codec/v2/encode.test.ts @@ -29,6 +29,12 @@ import { getCallbackHash, AxiomV2FeeData, encodeFullQueryV2, + HeaderSubquery, + AccountSubquery, + StorageSubquery, + TxSubquery, + ReceiptSubquery, + SolidityNestedMappingSubquery, } from "../../../src"; import { BLOCK_NUMBER, @@ -277,14 +283,14 @@ describe("Encoder V2", () => { subqueryData: { blockNumber, fieldIdx, - }, + } as HeaderSubquery, }, { type: DataSubqueryType.Header, subqueryData: { blockNumber: blockNumber + 1, fieldIdx: fieldIdx + 1, - }, + } as HeaderSubquery, }, { type: DataSubqueryType.Account, @@ -292,7 +298,7 @@ describe("Encoder V2", () => { blockNumber, addr, fieldIdx, - }, + } as AccountSubquery, }, { type: DataSubqueryType.Storage, @@ -300,7 +306,7 @@ describe("Encoder V2", () => { blockNumber, addr, slot, - }, + } as StorageSubquery, }, { type: DataSubqueryType.Transaction, @@ -308,7 +314,7 @@ describe("Encoder V2", () => { blockNumber: 15060942, txIdx: 114, fieldOrCalldataIdx, - }, + } as TxSubquery, }, { type: DataSubqueryType.Receipt, @@ -318,7 +324,7 @@ describe("Encoder V2", () => { fieldOrLogIdx, topicOrDataOrAddressIdx, eventSchema: "0x255910aca2752f3c05fcb4a54d3d8d93bb809a9c8cc215d5eed2504d44cbd865", - }, + } as ReceiptSubquery, }, { type: DataSubqueryType.SolidityNestedMapping, @@ -328,7 +334,7 @@ describe("Encoder V2", () => { mappingSlot, mappingDepth, keys, - }, + } as SolidityNestedMappingSubquery, }, ]; diff --git a/test/ipfs/scenarios.test.ts b/test/ipfs/scenarios.test.ts index ac7f014..69a0d32 100644 --- a/test/ipfs/scenarios.test.ts +++ b/test/ipfs/scenarios.test.ts @@ -50,7 +50,7 @@ describe("Additional IPFS scenarios to test", () => { }; } } - }, 30000); + }, 50000); test(`Read all pinned data`, async () => { for await (const client of ipfsClients) { @@ -64,7 +64,7 @@ describe("Additional IPFS scenarios to test", () => { } } } - }, 30000); + }, 60000); test(`Unpin all data`, async () => { for await (const client of ipfsClients) { @@ -73,5 +73,5 @@ describe("Additional IPFS scenarios to test", () => { expect(unpin.value as boolean).toEqual(true); } } - }, 30000); + }, 50000); }); \ No newline at end of file diff --git a/test/rpc/chainDataGoerli.test.ts b/test/rpc/chainDataGoerli.test.ts deleted file mode 100644 index 90b9586..0000000 --- a/test/rpc/chainDataGoerli.test.ts +++ /dev/null @@ -1,282 +0,0 @@ -import { ethers } from "ethers"; -import { - getAccountData, - getAccountFieldValue, - getBlockNumberAndTxIdx, - getFieldIdxHeaderExtraDataLen, - getFieldIdxTxContractDataIdx, - getFieldIdxTxDataLength, - getFullBlock, - getHeaderFieldValue, - getRawReceipt, - getRawTransaction, - getReceiptFieldValue, - getSolidityNestedMappingValue, - getStorageFieldValue, - getTxFieldValue, - getTxHash, -} from "../../src"; -import { - AccountField, - HeaderField, - ReceiptField, - TxField, - bytes32, -} from "../../src"; -import { - getFieldIdxHeaderLogsBloomIdx, - getFieldIdxHeaderTxHash, - getFieldIdxHeaderTxSize, - getFieldIdxTxCalldataIdx, - getFieldIdxTxType, - getFieldIdxTxBlockNumber, - getFieldIdxTxIndex, - getFieldIdxTxFunctionSelector, - getFieldIdxTxCalldataHash, - getFieldIdxReceiptTxType, - getFieldIdxReceiptBlockNumber, - getFieldIdxReceiptTxIndex, - getFieldIdxReceiptLogIdx, - getFieldIdxReceiptDataIdx, - getFieldIdxReceiptLogAddress, -} from "../../src"; -import fs from "fs"; -import { AxiomV2FieldConstant } from "../../src/constants"; - -function getGoerliTestCases(subquery: string): any { - const testCases = fs.readFileSync("test/rpc/data/goerli/" + subquery + ".json", "utf8"); - return JSON.parse(testCases); -} - -export function getHeaderGoerliTestCases(): any { - return getGoerliTestCases("header"); -} -export function getAccountGoerliTestCases(): any { - return getGoerliTestCases("account"); -} -export function getStorageGoerliTestCases(): any { - return getGoerliTestCases("storage"); -} -export function getTxGoerliTestCases(): any { - return getGoerliTestCases("tx"); -} -export function getReceiptGoerliTestCases(): any { - return getGoerliTestCases("receipt"); -} - -describe("ChainData query tests", () => { - const MATIC_ADDR = "0xDA5F92B81B7095b5763a09BD4A668DcfE6F3b133"; - const UNI_V3_FACTORY_ADDR = "0x1F98431c8aD98523631AE4a59f267346ea31F984"; - - const provider = new ethers.JsonRpcProvider(process.env.PROVIDER_URI_GOERLI as string); - const headerTestCases = getHeaderGoerliTestCases(); - const accountTestCases = getAccountGoerliTestCases(); - const storageTestCases = getStorageGoerliTestCases(); - const txTestCases = getTxGoerliTestCases(); - const receiptTestCases = getReceiptGoerliTestCases(); - - test("get header fields", async () => { - for (const { subquery, value } of headerTestCases["get header fields"]) { - const field_value = await getHeaderFieldValue(provider, subquery); - expect(field_value).toEqual(value); - } - }, 10000); - - test("header field negative test cases", async () => { - // Shanghai upgrade for withdrawalsRoot was at block 1000000 - const withdrawalsRoot = await getHeaderFieldValue(provider, { blockNumber: 1000000, fieldIdx: HeaderField.WithdrawalsRoot }); - expect(withdrawalsRoot).toEqual(null); - }, 10000); - - test("get special header fields", async () => { - for (const { subquery, value } of headerTestCases["get special header fields"]) { - const field_value = await getHeaderFieldValue(provider, subquery); - expect(field_value).toEqual(value); - } - }, 10000); - - test("get header field logs bloom", async () => { - for (const { subquery, value } of headerTestCases["get header field logs bloom"]) { - const field_value = await getHeaderFieldValue(provider, subquery); - expect(field_value).toEqual(value); - } - }, 10000); - - test("get account fields", async () => { - for (const { subquery, value } of accountTestCases["get account fields"]) { - const field_value = await getAccountFieldValue(provider, subquery); - expect(field_value).toEqual(value); - } - }, 10000); - - test("get storage slot", async () => { - for (const { subquery, value } of storageTestCases["get storage slot"]) { - const field_value = await getStorageFieldValue(provider, subquery); - expect(field_value).toEqual(value); - } - }, 10000); - - test("get tx field value", async () => { - for (const { subquery, value } of txTestCases["get tx field value"]) { - const field_value = await getTxFieldValue(provider, subquery); - expect(field_value).toEqual(value); - } - }, 10000); - - test("get problem tx field value", async () => { - for (const { subquery, value } of txTestCases["get problem tx field value"]) { - const field_value = await getTxFieldValue(provider, subquery); - expect(field_value).toEqual(value); - } - }, 10000); - - test("get problem receipt field value (log data size too large)", async () => { - for (const { subquery, value } of receiptTestCases["get problem receipt field value (log data size too large)"]) { - const field_value = await getReceiptFieldValue(provider, subquery); - expect(field_value).toEqual(value); - } - }, 10000); - - // test("get tx calldataIdx value", async () => { - // // for txHash = "0xe64c1d17a69ee91d41f054fd981f4ad073d9f807e1ddfad78b4a696a4a79f921"; - // const blockNumber = 9800000; - // const txIdx = 5; - // let calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(0) }); - // expect(calldataValue).toEqual("0x0000000000000000000000000000000000000000000000000000000000000100"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(1) }); - // expect(calldataValue).toEqual("0x000000000000000000000000b392448932f6ef430555631f765df0dfae34eff3"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(2) }); - // expect(calldataValue).toEqual("0x0000000000000000000000000000000000000000000000000000000001e13380"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(3) }); - // expect(calldataValue).toEqual("0x9923eb9400000003082a0a4936bd94a9078de18bea9fb1e023ecfb31b44c5f9d"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(4) }); - // expect(calldataValue).toEqual("0x000000000000000000000000231b0ee14048e9dccd1d247744d114a4eb5e8e63"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(5) }); - // expect(calldataValue).toEqual("0x0000000000000000000000000000000000000000000000000000000000000140"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(6) }); - // expect(calldataValue).toEqual("0x0000000000000000000000000000000000000000000000000000000000000001"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(7) }); - // expect(calldataValue).toEqual("0x0000000000000000000000000000000000000000000000000000000000000000"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(8) }); - // expect(calldataValue).toEqual("0x0000000000000000000000000000000000000000000000000000000000000006"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(9) }); - // expect(calldataValue).toEqual("0x7a65726f6b700000000000000000000000000000000000000000000000000000"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(10) }); - // expect(calldataValue).toEqual("0x0000000000000000000000000000000000000000000000000000000000000001"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(11) }); - // expect(calldataValue).toEqual("0x0000000000000000000000000000000000000000000000000000000000000020"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(12) }); - // expect(calldataValue).toEqual("0x00000000000000000000000000000000000000000000000000000000000000a4"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(13) }); - // expect(calldataValue).toEqual("0x8b95dd717610115e31b8be283a240f1b8ea09ca53abfdfaa17c79175efd8cfef"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(14) }); - // expect(calldataValue).toEqual("0x62b37ab900000000000000000000000000000000000000000000000000000000"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(15) }); - // expect(calldataValue).toEqual("0x0000003c00000000000000000000000000000000000000000000000000000000"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(16) }); - // expect(calldataValue).toEqual("0x0000006000000000000000000000000000000000000000000000000000000000"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(17) }); - // expect(calldataValue).toEqual("0x00000014b392448932f6ef430555631f765df0dfae34eff30000000000000000"); - // calldataValue = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxCalldataIdx(18) }); - // expect(calldataValue).toEqual("0x0000000000000000000000000000000000000000000000000000000000000000"); - // }, 10000); - - // test("get tx contract data field values", async () => { - // // Contract creation - // const contractCreateTxHash = "0x5a532ae8eb36dad0058b78f00ee459c42d58157dc11cc290e939b8aa91aa59d4"; - // const { blockNumber, txIdx } = await getBlockNumberAndTxIdx(provider, contractCreateTxHash) as { blockNumber: number, txIdx: number }; - // let value = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxContractDataIdx(0) }); - // expect(value).toEqual("0x6060604052341561000c57fe5b5b60018054600160a060020a033316600160a0"); - // value = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxContractDataIdx(284) }); - // expect(value).toEqual("0xf517e648a165627a7a72305820c3039feace276128a8a24bc387d61714eecae7"); - // value = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxContractDataIdx(285) }); - // expect(value).toEqual("0x40de955c6578526a4a4027bebc00290000000000000000000000000000000000"); - // }, 10000); - - test("get tx special field values", async () => { - for (const { subquery, value } of txTestCases["get tx special field values"]) { - const field_value = await getTxFieldValue(provider, subquery); - expect(field_value).toEqual(value); - } - - // // Contract creation - // NOTE: Incomplete for Goerli - // const contractCreateTxHash = "0x5a532ae8eb36dad0058b78f00ee459c42d58157dc11cc290e939b8aa91aa59d4"; - // const { blockNumber: contractCreateBlockNumber, txIdx: contractCreateTxIdx } = await getBlockNumberAndTxIdx(provider, contractCreateTxHash) as { blockNumber: number, txIdx: number }; - // value = await getTxFieldValue(provider, { blockNumber: contractCreateBlockNumber, txIdx: contractCreateTxIdx, fieldOrCalldataIdx: getFieldIdxTxFunctionSelector() }); - // expect(value).toEqual(bytes32(AxiomV2FieldConstant.Tx.ContractDeploySelectorValue)); - - // // EOA transfer - // const eoaTransferTxHash = "0xb1257d8484c43929d7bae46b2aecd509e5d9278273063c9bac2a2d9cb4f1c9f1"; - // const { blockNumber: eoaTransferBlockNumber, txIdx: eoaTransferTxIdx } = await getBlockNumberAndTxIdx(provider, eoaTransferTxHash) as { blockNumber: number, txIdx: number }; - // value = await getTxFieldValue(provider, { blockNumber: eoaTransferBlockNumber, txIdx: eoaTransferTxIdx, fieldOrCalldataIdx: getFieldIdxTxFunctionSelector() }); - // expect(value).toEqual(bytes32(AxiomV2FieldConstant.Tx.NoCalldataSelectorValue)); - - // value = await getTxFieldValue(provider, { blockNumber, txIdx, fieldOrCalldataIdx: getFieldIdxTxDataLength() }); - // expect(value).toEqual("0x0000000000000000000000000000000000000000000000000000000000011104"); - }, 10000); - - test("get receipt field value", async () => { - for (const { subquery, value } of receiptTestCases["get receipt field value"]) { - const field_value = await getReceiptFieldValue(provider, subquery); - expect(field_value).toEqual(value); - } - }, 10000); - - test("get receipt logsBloom field value", async () => { - for (const { subquery, value } of receiptTestCases["get receipt logsBloom field value"]) { - const field_value = await getReceiptFieldValue(provider, subquery); - expect(field_value).toEqual(value); - } - }, 10000); - - // test("get receipt special field value", async () => { - // const txHash = "0x190414997454151f9bd4bc9c60fbae709bd2301f4d36adbe246b27157dde83ac"; // rug tx? - // const { blockNumber, txIdx } = await getBlockNumberAndTxIdx(provider, txHash) as { blockNumber: number, txIdx: number }; - // let value = await getReceiptFieldValue(provider, { blockNumber, txIdx, fieldOrLogIdx: getFieldIdxReceiptTxType(), eventSchema: ethers.ZeroHash, topicOrDataOrAddressIdx: 0 }); - // expect(value).toEqual(bytes32(2)); - // value = await getReceiptFieldValue(provider, { blockNumber, txIdx, fieldOrLogIdx: getFieldIdxReceiptBlockNumber(), eventSchema: ethers.ZeroHash, topicOrDataOrAddressIdx: 0 }); - // expect(value).toEqual(bytes32(17500000)); - // value = await getReceiptFieldValue(provider, { blockNumber, txIdx, fieldOrLogIdx: getFieldIdxReceiptTxIndex(), eventSchema: ethers.ZeroHash, topicOrDataOrAddressIdx: 0 }); - // expect(value).toEqual(bytes32(119)); - // }, 10000); - - // test("get receipt logIdx value", async () => { - // const txHash = "0xe64c1d17a69ee91d41f054fd981f4ad073d9f807e1ddfad78b4a696a4a79f921"; - // const { blockNumber, txIdx } = await getBlockNumberAndTxIdx(provider, txHash) as { blockNumber: number, txIdx: number }; - - // const eventSchema = "0x65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af752"; - // let receiptValue = await getReceiptFieldValue(provider, { blockNumber, txIdx, fieldOrLogIdx: getFieldIdxReceiptLogIdx(7), eventSchema, topicOrDataOrAddressIdx: 0 }); - // expect(receiptValue).toEqual("0x65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af752"); - // receiptValue = await getReceiptFieldValue(provider, { blockNumber, txIdx, fieldOrLogIdx: getFieldIdxReceiptLogIdx(7), eventSchema, topicOrDataOrAddressIdx: 1 }); - // expect(receiptValue).toEqual("0x7610115e31b8be283a240f1b8ea09ca53abfdfaa17c79175efd8cfef62b37ab9"); - // receiptValue = await getReceiptFieldValue(provider, { blockNumber, txIdx, fieldOrLogIdx: getFieldIdxReceiptLogIdx(7), eventSchema, topicOrDataOrAddressIdx: 2 }); - // // Expect invalid topic index - // expect(receiptValue).toEqual(null); - // receiptValue = await getReceiptFieldValue(provider, { blockNumber, txIdx, fieldOrLogIdx: getFieldIdxReceiptLogIdx(7), eventSchema, topicOrDataOrAddressIdx: getFieldIdxReceiptDataIdx(0) }); - // expect(receiptValue).toEqual("0x000000000000000000000000000000000000000000000000000000000000003c"); - // receiptValue = await getReceiptFieldValue(provider, { blockNumber, txIdx, fieldOrLogIdx: getFieldIdxReceiptLogIdx(7), eventSchema, topicOrDataOrAddressIdx: getFieldIdxReceiptDataIdx(1) }); - // expect(receiptValue).toEqual("0x0000000000000000000000000000000000000000000000000000000000000040"); - // receiptValue = await getReceiptFieldValue(provider, { blockNumber, txIdx, fieldOrLogIdx: getFieldIdxReceiptLogIdx(7), eventSchema, topicOrDataOrAddressIdx: getFieldIdxReceiptDataIdx(2) }); - // expect(receiptValue).toEqual("0x0000000000000000000000000000000000000000000000000000000000000014"); - // receiptValue = await getReceiptFieldValue(provider, { blockNumber, txIdx, fieldOrLogIdx: getFieldIdxReceiptLogIdx(7), eventSchema, topicOrDataOrAddressIdx: getFieldIdxReceiptDataIdx(3) }); - // expect(receiptValue).toEqual("0xb392448932f6ef430555631f765df0dfae34eff3000000000000000000000000"); - // receiptValue = await getReceiptFieldValue(provider, { blockNumber, txIdx, fieldOrLogIdx: getFieldIdxReceiptLogIdx(7), eventSchema, topicOrDataOrAddressIdx: getFieldIdxReceiptLogAddress() }); - // expect(receiptValue).toEqual(bytes32('0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63')); - // }, 10000); - - // test("Get solidity nested mapping value", async () => { - // const blockNumber = 9000000; - // const addr = UNI_V3_FACTORY_ADDR; - // const mappingSlot = "5"; - // const mappingDepth = 3; - // const keys: [string, string, string, string] = [ - // bytes32("0x0000000000085d4780b73119b644ae5ecd22b376"), - // bytes32("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"), - // bytes32(3000), - // "", - // ]; - // const value = await getSolidityNestedMappingValue(provider, { blockNumber, addr, mappingSlot, mappingDepth, keys }); - // expect(value).toEqual(bytes32("0xf5148fbdae394c553d019b4caeffc5f845dcd12c")); - // }, 10000); -}); diff --git a/test/rpc/chainDataOpstack.test.ts b/test/rpc/chainDataOpstack.test.ts new file mode 100644 index 0000000..673e933 --- /dev/null +++ b/test/rpc/chainDataOpstack.test.ts @@ -0,0 +1,96 @@ +import { ethers } from "ethers"; +import { getBlockNumberAndTxIdx, getTxFieldValue, TxField } from "../../src"; + +const optimismTx = [ + "0x25214e8c125f7c9749614d8f81e162e4cca5c86a94d532628edc70c3016163e2", + "0x58f48d2419d09a1797de977e1c4fdffc49b32a799c8d493479a5882201309469", + "0x0c369868122e1af5d10d43e67bc970e1b62444be4ea8886e1fad6234b86b431f", +] + +const optimismSystem = [ + "0xbd5ac52db73613d6586832ce34762ba6a1e1f241d8d9e6e6412acbab32054a41", + "0x1406a2d4cde0551c8b5837bb51233f18e375fdf303ce6ace10fca9dc8fed9c71", + "0x65189cfa8f7678b058e88de47dbb8c74635598bc7e441dc8d180803d357605d4", +]; + +const baseTx = [ + "0x3ed6efd80791ab4108c2ea9e696100b79e83e82f0ae4d6087e189b90bb1b22e8", + "0xa4f3f097bae6aab76a035440effa0b752cb56d9098c25f709624315c7ffd19a9", + "0x012c8d77174aa6ab8e63933a2f74f69fe9820915ab44c5d844da9c7276a51ff0", +]; + +const baseSystem = [ + "0xcbbe74fd041d136b4bccab96f50a32e41326afb464ae69727b19cdf78e6ff03b", + "0x5eb5119f26565c90ff816ae74869459b9338694196cedd0f26ca04831643d413", + "0xe990e2c2531707144a6d60d4a74f0d19f8e905b9065678988e3f1a70d20db05a", +]; + +describe("Chaindata OpStack", () => { + const providerOptimism = new ethers.JsonRpcProvider( + process.env.PROVIDER_URI_10 as string, + ); + + const providerBase = new ethers.JsonRpcProvider( + process.env.PROVIDER_URI_8453 as string, + ); + + test("Optimism: Check that we allow tx types < 0x03", async () => { + for await (const txHash of optimismTx) { + const { blockNumber, txIdx } = await getBlockNumberAndTxIdx(providerOptimism, txHash); + if (blockNumber === null || txIdx === null) { + throw new Error("Error getting block number and tx idx"); + } + const val = await getTxFieldValue(providerOptimism, { + blockNumber, + txIdx, + fieldOrCalldataIdx: TxField.To, + }); + expect(val).not.toBeNull(); + } + }); + + test("Optimism: Check that we block tx type 0x7E", async () => { + for await (const txHash of optimismSystem) { + const { blockNumber, txIdx } = await getBlockNumberAndTxIdx(providerOptimism, txHash); + if (blockNumber === null || txIdx === null) { + throw new Error("Error getting block number and tx idx"); + } + const val = await getTxFieldValue(providerOptimism, { + blockNumber, + txIdx, + fieldOrCalldataIdx: TxField.To, + }); + expect(val).toBeNull(); + } + }); + + test("Base: Check that we allow tx types < 0x03", async () => { + for await (const txHash of baseTx) { + const { blockNumber, txIdx } = await getBlockNumberAndTxIdx(providerBase, txHash); + if (blockNumber === null || txIdx === null) { + throw new Error("Error getting block number and tx idx"); + } + const val = await getTxFieldValue(providerBase, { + blockNumber, + txIdx, + fieldOrCalldataIdx: TxField.To, + }); + expect(val).not.toBeNull(); + } + }); + + test("Base: Check that we block tx type 0x7E", async () => { + for await (const txHash of baseSystem) { + const { blockNumber, txIdx } = await getBlockNumberAndTxIdx(providerBase, txHash); + if (blockNumber === null || txIdx === null) { + throw new Error("Error getting block number and tx idx"); + } + const val = await getTxFieldValue(providerBase, { + blockNumber, + txIdx, + fieldOrCalldataIdx: TxField.To, + }); + expect(val).toBeNull(); + } + }); +}); diff --git a/test/utils/gasCalc.test.ts b/test/utils/gasCalc.test.ts new file mode 100644 index 0000000..55db1c3 --- /dev/null +++ b/test/utils/gasCalc.test.ts @@ -0,0 +1,19 @@ +import { calculateCalldataGas } from "../../src"; + +// Test coverage areas: +// - Calldata gas calculator + +describe("Calldata Gas Calculator", () => { + test("basic calculator test", () => { + const gas = calculateCalldataGas("0x123456789000"); + expect(gas).toEqual(84); + }); + + test("arbitrary gas cost", () => { + const oldVkey = "0x0001000009000100000004010000010080000000000000000000000000000000c562ed60c110f4e0ca53d33b0e1fe0d1fc10db6d997001813ecd409d378f220cc04b25057d0bddf35d4542077516abb76445b8e745a457e3ccc1bf9aac2ba406977facb333a6cae3726c695dceea3b6a2a4ddce29428b70ddd989ea1fe60014f25443655c0b66da8a310f273dd57db7843cd3800fa5d24c415c3e13b5f035a6b000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080c28c31d22d8f204e81b8fc714de26d87c1d4c756632cad0668655fd09220762a2f3064cf682958accb92639a8a276e8d491b49c5f2d1557fe686e8805641f21922e4c62aacfc240ed0553bfad00122ba8c7627c870c739f3f818584e066a8b1f841485e0a9f109688bdc4f5ff851d9e2e44833ae573456742c1237322e93854279a62f1cc2f1440cc9fdcd534b612a49da4b6139bbed8cf53a26f4568ac3f567e40c0e4521b32cf17ce45eee625a7e525481b412984310e1fb44eef5a34ab34cf4d1a7e36933bfb413c2f451097e4cd1ab67e8a4cb0a1bdac2d05284e48be45e"; + const newVkey = "0x0001000009000100000014030000010080000000000000000000000000000000c60fa9c24296296126123ba55b4a1cdf65d078c61351a288f7fe424e48f6f81bc04b25057d0bddf35d4542077516abb76445b8e745a457e3ccc1bf9aac2ba406977facb333a6cae3726c695dceea3b6a2a4ddce29428b70ddd989ea1fe60014f25443655c0b66da8a310f273dd57db7843cd3800fa5d24c415c3e13b5f035a6b0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080c28c31d22d8f204e81b8fc714de26d87c1d4c756632cad0668655fd09220762ac97e680c26aa7578d2a619a036f989a54d69901c0dfebe50e4550c91e77aff6622e4c62aacfc240ed0553bfad00122ba8c7627c870c739f3f818584e066a8b1f841485e0a9f109688bdc4f5ff851d9e2e44833ae573456742c1237322e93854279a62f1cc2f1440cc9fdcd534b612a49da4b6139bbed8cf53a26f4568ac3f567e40c0e4521b32cf17ce45eee625a7e525481b412984310e1fb44eef5a34ab34c62ee0fe9aa8394ac79f7db54f83e432a353c7f066c180a9e7a7a37d8d1a19621797cae9e008e1a1c6179a2669e046910e331c74b4e57daa2e643d7890a9ffe42ce5a4cc0f54b73ff0bcedb8c86a757af5e46284d55d21880e1a0a5fb244b0261e55f1e07004fb3e7beed33d7e81056d3aa999d1dd24a44f9aa260809521c156e3fa7d77341d8aa211ce29a49741679c8f72e90b0390993d99c6d8c0aaac11d57b76b2ff2659b4946451a50ff328d54bc43c0b63aa8918a58c07a4341317335060492eec333e48f59fe81084a4736040410107225455b86fa305be40e8a87fb081e80637e88a5119875eb33158d940b2e9d329d7b789a255cb0046b30b104fd10197bad10d254ed326b9f05b266b708e494b3c0d51e1029cc45cc733dddec406d0bfd7893d41759553d6bf679e019ebf724d06bf4c90a06290c16e94e31fe6e2882f323b6df6e395c26e47adac9c17a3e523baac0032760248f6cba2d26b3a606a038b067a84e5393fc5a765d129ba9623dbd01440dd62cf50bc20778c64d3e11d43319b40899edee653a91cdf3e54cc87b8a872e8c60228a51494bfd095c856ba7dfc2ccf04eeb0022d8c1d6c4afb79c908f5badd91a6ca58b4a9683edac8b2c0b239c177ecb6c67c8c45eee7e7398e12e96f7e42c80e2638960a2b367a026016c4e6756b257b8be2ca2553d710b966c469d7f976e4d3694f9bb86300db5886468609c0ad2b8ca67724c13e56a430669835624483db35d2217c517d74f9b864a0df9bbba485cc4c479ef23f0934510a5d86445a424ad80f5c68c62590b8f244da2d4a115c90c5ffa24d12d55d16890778e67b5085bc11ec9c15257c8ddffe025"; + const oldGas = calculateCalldataGas(oldVkey); + const newGas = calculateCalldataGas(newVkey); + expect(oldGas).toBeLessThan(newGas); + }) +});