diff --git a/packages/arc-index/README.md b/packages/arc-index/README.md index 4e62b25..1e97bf4 100644 --- a/packages/arc-index/README.md +++ b/packages/arc-index/README.md @@ -66,6 +66,25 @@ Replay every indexed movement for an address and compare against node --test 'test/*.test.ts' ``` -10 tests against canned logs, no network. They pin the pairing rule (matching +The synthetic cases use canned logs, no network. They pin the pairing rule (matching `from`, `to`, and `value × 10¹²`), one-to-one log consumption, dust truncation, the self-transfer and zero-value exceptions, and that net deltas sum to zero. + +### Mainnet escrow receipt fixture + +[Issue #1](https://github.com/ilkermanap/arctools/issues/1) describes ArcBounty job +#4's payout on Arc mainnet (chain ID 5042). The +[saved JSON-RPC response](test/fixtures/mainnet-escrow-payout.receipt.json) was +retrieved separately through BlockVectra's keyed Arc endpoint on +2026-11-07 at 22:46 UTC, after an `eth_chainId` check returned 5042. It is not the +issue author's earlier saved copy. The response has SHA-256 +`5a391370682effce1dc8fe057ec4d259b53fd2a353c13b22a73e570000bef1b4`. + +The offline test feeds its six USDC `Transfer` logs through the normal scanner: +2 USDC escrow → adapter, 0.02 USDC adapter → fee recipient, and 1.98 USDC +adapter → worker. It checks three movements, a zero adapter delta, and the +worker's 1.98 USDC delta. Gross transfer flow is 4 USDC, not worker earnings. + +This is one saved receipt, not a live RPC test or proof of archive coverage, +canonicality, finality, gas accounting, or all of the wallet's balances. No API +key is included or required to run the test. diff --git a/packages/arc-index/test/fixtures/mainnet-escrow-payout.receipt.json b/packages/arc-index/test/fixtures/mainnet-escrow-payout.receipt.json new file mode 100644 index 0000000..a85ad5f --- /dev/null +++ b/packages/arc-index/test/fixtures/mainnet-escrow-payout.receipt.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":2,"result":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x59568c","logs":[{"address":"0xfffffffffffffffffffffffffffffffffffffffe","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000064ca39fc57315d0d488accac07c37c6e841cd058","0x00000000000000000000000073c617e808ed5c7ca41413dfc6ee940ddcbb0b8d"],"data":"0x0000000000000000000000000000000000000000000000001bc16d674ec80000","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","blockTimestamp":"0x6aab83a7","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","logIndex":"0x33","removed":false},{"address":"0x3600000000000000000000000000000000000000","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000064ca39fc57315d0d488accac07c37c6e841cd058","0x00000000000000000000000073c617e808ed5c7ca41413dfc6ee940ddcbb0b8d"],"data":"0x00000000000000000000000000000000000000000000000000000000001e8480","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","blockTimestamp":"0x6aab83a7","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","logIndex":"0x34","removed":false},{"address":"0x64ca39fc57315d0d488accac07c37c6e841cd058","topics":["0x0fd54bd364fa9e67f17b091aefe930932c09fe7651cf5ad02c71a418f3341444","0x0000000000000000000000000000000000000000000000000000000000000004","0x00000000000000000000000073c617e808ed5c7ca41413dfc6ee940ddcbb0b8d"],"data":"0x2b29265fc125740ae6bbc5035ae7af720b6932f4a3e44ba5ac02955c21ca9a05","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","blockTimestamp":"0x6aab83a7","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","logIndex":"0x35","removed":false},{"address":"0x64ca39fc57315d0d488accac07c37c6e841cd058","topics":["0x21d71db5be59bb9fa133895586b7404307dd33fb93b16db09dc6f1d9d7d231b0","0x0000000000000000000000000000000000000000000000000000000000000004","0x00000000000000000000000073c617e808ed5c7ca41413dfc6ee940ddcbb0b8d"],"data":"0x00000000000000000000000000000000000000000000000000000000001e8480","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","blockTimestamp":"0x6aab83a7","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","logIndex":"0x36","removed":false},{"address":"0xfffffffffffffffffffffffffffffffffffffffe","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000073c617e808ed5c7ca41413dfc6ee940ddcbb0b8d","0x000000000000000000000000adac7534d3fe868e28c77df5cd930f2635bcb63a"],"data":"0x00000000000000000000000000000000000000000000000000470de4df820000","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","blockTimestamp":"0x6aab83a7","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","logIndex":"0x37","removed":false},{"address":"0x3600000000000000000000000000000000000000","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000073c617e808ed5c7ca41413dfc6ee940ddcbb0b8d","0x000000000000000000000000adac7534d3fe868e28c77df5cd930f2635bcb63a"],"data":"0x0000000000000000000000000000000000000000000000000000000000004e20","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","blockTimestamp":"0x6aab83a7","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","logIndex":"0x38","removed":false},{"address":"0x73c617e808ed5c7ca41413dfc6ee940ddcbb0b8d","topics":["0xe2dc319d02740d7f5da7acdbf749fa867feaba2b43abee72dcc24832f052694b","0x0000000000000000000000000000000000000000000000000000000000000004","0x000000000000000000000000adac7534d3fe868e28c77df5cd930f2635bcb63a"],"data":"0x0000000000000000000000000000000000000000000000000000000000004e20","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","blockTimestamp":"0x6aab83a7","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","logIndex":"0x39","removed":false},{"address":"0xfffffffffffffffffffffffffffffffffffffffe","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000073c617e808ed5c7ca41413dfc6ee940ddcbb0b8d","0x000000000000000000000000092f4483526ebc2476c247cb88d166adb7c3232f"],"data":"0x0000000000000000000000000000000000000000000000001b7a5f826f460000","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","blockTimestamp":"0x6aab83a7","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","logIndex":"0x3a","removed":false},{"address":"0x3600000000000000000000000000000000000000","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000073c617e808ed5c7ca41413dfc6ee940ddcbb0b8d","0x000000000000000000000000092f4483526ebc2476c247cb88d166adb7c3232f"],"data":"0x00000000000000000000000000000000000000000000000000000000001e3660","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","blockTimestamp":"0x6aab83a7","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","logIndex":"0x3b","removed":false},{"address":"0x8004baa17c55a88189ae136b182e5fda19de9b63","topics":["0x6a4a61743519c9d648a14e6493f47dbe3ff1aa29e7785c96c8326a205e58febc","0x000000000000000000000000000000000000000000000000000000000000000e","0x00000000000000000000000073c617e808ed5c7ca41413dfc6ee940ddcbb0b8d","0x76ac6749717e9473a38cc41403e8a516d150b9abafee5886f56aef4995c3b4d6"],"data":"0x0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000180e64d767f1444f197137c1b507b1c87e16900d3f7f7583089566e17e97a5f88fc0000000000000000000000000000000000000000000000000000000000000010626f756e74795f636f6d706c6574656400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","blockTimestamp":"0x6aab83a7","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","logIndex":"0x3c","removed":false},{"address":"0x73c617e808ed5c7ca41413dfc6ee940ddcbb0b8d","topics":["0x51e8d4f8aaf9c60ffae4405a481bb91e06484535112745e154a147feb6a30303","0x0000000000000000000000000000000000000000000000000000000000000004"],"data":"0x000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000005f","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","blockTimestamp":"0x6aab83a7","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","logIndex":"0x3d","removed":false}],"logsBloom":"0x00000000000020000000000000010100000084000000004410000000000000002000000000000200000000001000000000410000000000400000000000000000000000000001000800000008000000000100000000000008800000000000000008000000040000002000000002000000000001000000000400000010800000440000000000000000000000000000008008040001000800000000000820000000000000000040000000000000020000000000000000000020002000008000000200000002000000000008000004000002000000008000000000000800000000400000008000000000000000000000000000000000000000000000000040080000","transactionHash":"0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3","transactionIndex":"0x18","blockHash":"0xad511f00fc2c77cc364675cf26dcb14664c1c992ea5d0576d325ec38064ff936","blockNumber":"0x144bf6e","gasUsed":"0x3ef6d","effectiveGasPrice":"0x4a817c801","from":"0xde427f3967cc7a0bf7a9f891195760ccffc82eda","to":"0x73c617e808ed5c7ca41413dfc6ee940ddcbb0b8d","contractAddress":null}} \ No newline at end of file diff --git a/packages/arc-index/test/movements.test.ts b/packages/arc-index/test/movements.test.ts index 7025969..0de3f98 100644 --- a/packages/arc-index/test/movements.test.ts +++ b/packages/arc-index/test/movements.test.ts @@ -1,5 +1,6 @@ import { test } from "node:test"; import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; import type { Log } from "../../arc-common/rpc.ts"; import type { Hex } from "../../arc-common/abi.ts"; import { Rpc } from "../../arc-common/rpc.ts"; @@ -136,3 +137,41 @@ test("net deltas sum to zero across a closed set of transfers", async () => { const total = [...netDeltas(r.movements).values()].reduce((a, b) => a + b, 0n); assert.equal(total, 0n); }); + +// Real mainnet case suggested in https://github.com/ilkermanap/arctools/issues/1. +// The saved response is read locally: this test never calls an RPC endpoint. +test("a mainnet escrow payout pairs six Transfer logs into three movements", async () => { + const { result: receipt } = JSON.parse(readFileSync( + new URL("./fixtures/mainnet-escrow-payout.receipt.json", import.meta.url), "utf8", + )) as { result: { transactionHash: Hex; status: Hex; blockNumber: Hex; logs: Log[] } }; + assert.equal(receipt.transactionHash, + "0x73d026991436c92b1700af66f230b64a4004aa96758ce837cb732e6f253867b3"); + assert.equal(receipt.status, "0x1"); + + const transfers = receipt.logs.filter((entry) => entry.topics[0] === TRANSFER_TOPIC); + assert.equal(transfers.length, 6); + const block = BigInt(receipt.blockNumber); + const r = await scan(fakeRpc( + transfers.filter((entry) => entry.address.toLowerCase() === NATIVE_EMITTER), + transfers.filter((entry) => entry.address.toLowerCase() === ERC20_EMITTER), + ), block, block); + + const escrow = "0x64ca39fc57315d0d488accac07c37c6e841cd058" as Hex; + const adapter = "0x73c617e808ed5c7ca41413dfc6ee940ddcbb0b8d" as Hex; + const feeRecipient = "0xadac7534d3fe868e28c77df5cd930f2635bcb63a" as Hex; + const worker = "0x092f4483526ebc2476c247cb88d166adb7c3232f" as Hex; + assert.deepEqual(r.movements.map(({ from, to, value6, via }) => ({ from, to, value6, via })), [ + { from: escrow, to: adapter, value6: 2_000_000n, via: "erc20" }, + { from: adapter, to: feeRecipient, value6: 20_000n, via: "erc20" }, + { from: adapter, to: worker, value6: 1_980_000n, via: "erc20" }, + ]); + assert.deepEqual(r.anomalies, []); + + const deltas = netDeltas(r.movements); + assert.equal(deltas.get(escrow), -2_000_000n * SCALE); + assert.equal(deltas.get(adapter), 0n); + assert.equal(deltas.get(feeRecipient), 20_000n * SCALE); + assert.equal(deltas.get(worker), 1_980_000n * SCALE); + // Transfer flow includes the escrow-to-adapter leg; it is not worker earnings. + assert.equal(r.stats.canonicalVolume, 4_000_000n * SCALE); +});