diff --git a/bun.lockb b/bun.lockb index 597a2e00..6b7c7f0d 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index e5a3f5c7..226b7077 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "contracts/ReadBytesAt.sol" ], "devDependencies": { - "@adraffy/blocksmith": "^0.1.46", + "@adraffy/blocksmith": "^0.1.47", "@types/bun": "latest", "@typescript-eslint/eslint-plugin": "^6.7.4", "@typescript-eslint/parser": "^6.7.4", diff --git a/src/GatewayProvider.ts b/src/GatewayProvider.ts index 0c703059..9fba0bd6 100755 --- a/src/GatewayProvider.ts +++ b/src/GatewayProvider.ts @@ -25,7 +25,8 @@ export class GatewayProvider extends JsonRpcProvider { jsonrpc: '2.0', }), }); - const { result } = await res.json(); + const { result, error } = await res.json(); + if (!res.ok || error) throw new Error(error?.message ?? 'expected rpc'); return new this(new FetchRequest(url), BigInt(result)); } constructor( diff --git a/src/chains.ts b/src/chains.ts index 25a4a5b8..e9671368 100755 --- a/src/chains.ts +++ b/src/chains.ts @@ -45,6 +45,9 @@ export const CHAINS = { WORLD: 480n, WORLD_SEPOLIA: 4801n, APE: 33139n, + ZERO: 543210n, + ZERO_SEPOLIA: 4457845n, + INK_SEPOLIA: 763373n, } as const satisfies Record; export function chainName(chain: Chain): string { diff --git a/src/op/OPFaultRollup.ts b/src/op/OPFaultRollup.ts index 64d14a12..e80b0705 100755 --- a/src/op/OPFaultRollup.ts +++ b/src/op/OPFaultRollup.ts @@ -59,6 +59,14 @@ export class OPFaultRollup extends AbstractOPRollup { GameFinder: GAME_FINDER_SEPOLIA, }; + // https://docs.inkonchain.com/build/useful-info/ink-contracts#l1-testnet-contracts-sepolia + static readonly inkSepoliaConfig: RollupDeployment = { + chain1: CHAINS.SEPOLIA, + chain2: CHAINS.INK_SEPOLIA, + OptimismPortal: '0x5c1d29C6c9C8b0800692acC95D700bcb4966A1d7', + GameFinder: GAME_FINDER_SEPOLIA, + }; + // 20240917: delayed constructor not needed readonly OptimismPortal: Contract; readonly GameFinder: Contract; diff --git a/src/utils.ts b/src/utils.ts index f62e28fb..f1200de5 100755 --- a/src/utils.ts +++ b/src/utils.ts @@ -11,6 +11,7 @@ export const NULL_CODE_HASH = keccakStr(''); export const EVM_BLOCKHASH_DEPTH = 256; +// TODO: make this a function of Chain export const MAINNET_BLOCK_SEC = 12; export const LATEST_BLOCK_TAG = 'latest'; diff --git a/src/zksync/ZKSyncRollup.ts b/src/zksync/ZKSyncRollup.ts index 686fbb06..eedaff9e 100755 --- a/src/zksync/ZKSyncRollup.ts +++ b/src/zksync/ZKSyncRollup.ts @@ -38,11 +38,22 @@ export class ZKSyncRollup extends AbstractRollup { chain2: CHAINS.ZKSYNC, DiamondProxy: '0x32400084c286cf3e17e7b677ea9583e60a000324', }; - static readonly sepoliaConfig: RollupDeployment = { chain1: CHAINS.SEPOLIA, chain2: CHAINS.ZKSYNC_SEPOLIA, - DiamondProxy: '0x9a6de0f62Aa270A8bCB1e2610078650D539B1Ef9', + DiamondProxy: '0x9A6DE0f62Aa270A8bCB1e2610078650D539B1Ef9', + }; + + // https://docs.zero.network/main-features/system-contracts#zer%CE%B8-network + static readonly zeroMainnetConfig: RollupDeployment = { + chain1: CHAINS.MAINNET, + chain2: CHAINS.ZERO, + DiamondProxy: '0xdbD849acC6bA61F461CB8A41BBaeE2D673CA02d9', + }; + static readonly zeroSepoliaConfig: RollupDeployment = { + chain1: CHAINS.SEPOLIA, + chain2: CHAINS.ZERO_SEPOLIA, + DiamondProxy: '0x9A62B01fFa3bD358d03508ef60bB522ABA5d1bEb', }; readonly DiamondProxy: Contract; diff --git a/test/gateway/common.ts b/test/gateway/common.ts index 155e3eb8..af19594b 100755 --- a/test/gateway/common.ts +++ b/test/gateway/common.ts @@ -20,6 +20,10 @@ import { ScrollRollup, } from '../../src/scroll/ScrollRollup.js'; import { type LineaConfig, LineaRollup } from '../../src/linea/LineaRollup.js'; +import { + type ZKSyncConfig, + ZKSyncRollup, +} from '../../src/zksync/ZKSyncRollup.js'; import { EthSelfRollup } from '../../src/eth/EthSelfRollup.js'; import { TrustedRollup } from '../../src/TrustedRollup.js'; import { EthProver } from '../../src/eth/EthProver.js'; @@ -271,3 +275,33 @@ export function testLinea( await setupTests(verifier, opts); }); } + +export function testZKSync( + config: RollupDeployment, + opts: TestOptions +) { + describe.skipIf(shouldSkip(opts))(testName(config), async () => { + const rollup = new ZKSyncRollup(createProviderPair(config), config); + const foundry = await Foundry.launch({ + fork: providerURL(config.chain1), + infoLog: !!opts.log, + infiniteCallGas: true, // Blake2s is ~12m gas per proof! + }); + afterAll(foundry.shutdown); + const gateway = new Gateway(rollup); + const ccip = await serve(gateway, { protocol: 'raw', log: !!opts.log }); + afterAll(ccip.shutdown); + const GatewayVM = await foundry.deploy({ file: 'GatewayVM' }); + const ZKSyncSMT = await foundry.deploy({ file: 'ZKSyncSMT' }); + const hooks = await foundry.deploy({ + file: 'ZKSyncVerifierHooks', + args: [ZKSyncSMT], + }); + const verifier = await foundry.deploy({ + file: 'ZKSyncVerifier', + args: [[ccip.endpoint], rollup.defaultWindow, hooks, rollup.DiamondProxy], + libs: { GatewayVM }, + }); + await setupTests(verifier, opts); + }); +} diff --git a/test/gateway/ink-sepolia.test.ts b/test/gateway/ink-sepolia.test.ts new file mode 100755 index 00000000..01436c7d --- /dev/null +++ b/test/gateway/ink-sepolia.test.ts @@ -0,0 +1,10 @@ +import { OPFaultRollup } from '../../src/op/OPFaultRollup.js'; +import { testOPFault } from './common.js'; + +testOPFault(OPFaultRollup.inkSepoliaConfig, { + // https://explorer-sepolia.inkonchain.com/address/0x0d3e01829E8364DeC0e7475ca06B5c73dbA33ef6?tab=contract + slotDataContract: '0x0d3e01829E8364DeC0e7475ca06B5c73dbA33ef6', + // https://explorer-sepolia.inkonchain.com/address/0x57C2F437E0a5E155ced91a7A17bfc372C0aF7B05?tab=contract + slotDataPointer: '0x57C2F437E0a5E155ced91a7A17bfc372C0aF7B05', + skipCI: true, +}); diff --git a/test/gateway/zero.test.ts b/test/gateway/zero.test.ts new file mode 100755 index 00000000..b9afdfda --- /dev/null +++ b/test/gateway/zero.test.ts @@ -0,0 +1,8 @@ +import { ZKSyncRollup } from '../../src/zksync/ZKSyncRollup.js'; +import { testZKSync } from './common.js'; + +testZKSync(ZKSyncRollup.zeroMainnetConfig, { + // https://zerion-explorer.vercel.app/address/0x1Cd42904e173EA9f7BA05BbB685882Ea46969dEc#contract + slotDataContract: '0x1Cd42904e173EA9f7BA05BbB685882Ea46969dEc', + skipCI: true, +}); diff --git a/test/gateway/zksync-sepolia.test.ts b/test/gateway/zksync-sepolia.test.ts new file mode 100755 index 00000000..09103982 --- /dev/null +++ b/test/gateway/zksync-sepolia.test.ts @@ -0,0 +1,10 @@ +import { ZKSyncRollup } from '../../src/zksync/ZKSyncRollup.js'; +import { testZKSync } from './common.js'; + +testZKSync(ZKSyncRollup.sepoliaConfig, { + // https://sepolia.explorer.zksync.io/address/0x1Cd42904e173EA9f7BA05BbB685882Ea46969dEc#contract + slotDataContract: '0x1Cd42904e173EA9f7BA05BbB685882Ea46969dEc', + // https://sepolia.explorer.zksync.io/address/0x8D42501ADE3d0D02033B7FB6FfEa338828a1A467 + slotDataPointer: '0x8D42501ADE3d0D02033B7FB6FfEa338828a1A467', + skipCI: true, +}); diff --git a/test/gateway/zksync.test.ts b/test/gateway/zksync.test.ts index 592479f6..4076ad91 100755 --- a/test/gateway/zksync.test.ts +++ b/test/gateway/zksync.test.ts @@ -1,37 +1,10 @@ import { ZKSyncRollup } from '../../src/zksync/ZKSyncRollup.js'; -import { Gateway } from '../../src/gateway.js'; -import { serve } from '@resolverworks/ezccip/serve'; -import { Foundry } from '@adraffy/blocksmith'; -import { createProviderPair, providerURL } from '../providers.js'; -import { setupTests, testName } from './common.js'; -import { describe } from '../bun-describe-fix.js'; -import { afterAll } from 'bun:test'; +import { testZKSync } from './common.js'; -const config = ZKSyncRollup.mainnetConfig; -describe(testName(config), async () => { - const rollup = new ZKSyncRollup(createProviderPair(config), config); - const foundry = await Foundry.launch({ - fork: providerURL(config.chain1), - infoLog: false, - infiniteCallGas: true, // Blake2s is ~12m gas per proof! - }); - afterAll(foundry.shutdown); - const gateway = new Gateway(rollup); - const ccip = await serve(gateway, { protocol: 'raw', log: false }); - afterAll(ccip.shutdown); - const GatewayVM = await foundry.deploy({ file: 'GatewayVM' }); - const ZKSyncSMT = await foundry.deploy({ file: 'ZKSyncSMT' }); - const hooks = await foundry.deploy({ - file: 'ZKSyncVerifierHooks', - args: [ZKSyncSMT], - }); - const verifier = await foundry.deploy({ - file: 'ZKSyncVerifier', - args: [[ccip.endpoint], rollup.defaultWindow, hooks, rollup.DiamondProxy], - libs: { GatewayVM }, - }); - await setupTests(verifier, { - // https://explorer.zksync.io/address/0x1Cd42904e173EA9f7BA05BbB685882Ea46969dEc#contract - slotDataContract: '0x1Cd42904e173EA9f7BA05BbB685882Ea46969dEc', - }); +testZKSync(ZKSyncRollup.mainnetConfig, { + // https://explorer.zksync.io/address/0x1Cd42904e173EA9f7BA05BbB685882Ea46969dEc#contract + slotDataContract: '0x1Cd42904e173EA9f7BA05BbB685882Ea46969dEc', + // https://explorer.zksync.io/address/0x8D42501ADE3d0D02033B7FB6FfEa338828a1A467#contract + // TODO: enable this after batch 494047 is finalized + //slotDataPointer: '0x8D42501ADE3d0D02033B7FB6FfEa338828a1A467', }); diff --git a/test/providers.ts b/test/providers.ts index 62102088..c263e39d 100755 --- a/test/providers.ts +++ b/test/providers.ts @@ -264,6 +264,20 @@ export const RPC_INFO = new Map( // wss://rpc.apechain.com/ws // https://apechain.calderachain.xyz/http }, + // https://docs.zero.network/build-on-zero/network-information#zer%CE%B8-network + { + chain: CHAINS.ZERO, + rpc: 'https://rpc.zerion.io/v1/zero', + }, + { + chain: CHAINS.ZERO_SEPOLIA, + rpc: 'https://rpc.zerion.io/v1/zero-sepolia', + }, + // https://docs.inkonchain.com/quick-start/get-connected + { + chain: CHAINS.INK_SEPOLIA, + rpc: 'https://rpc-qnd-sepolia.inkonchain.com', // wss://rpc-qnd-sepolia.inkonchain.com + }, ] satisfies RPCInfo[] ).map((x) => [x.chain, x]) ); diff --git a/test/rollup/trusted.ts b/test/rollup/trusted.ts index 86244c9b..4d7be3d9 100755 --- a/test/rollup/trusted.ts +++ b/test/rollup/trusted.ts @@ -1,7 +1,7 @@ import { randomBytes, SigningKey } from 'ethers/crypto'; import { CHAINS } from '../../src/chains.js'; import { TrustedRollup } from '../../src/TrustedRollup.js'; -import { EthProver } from '../../src/index.js'; +import { EthProver } from '../../src/eth/EthProver.js'; import { createProvider } from '../providers.js'; const rollup = new TrustedRollup( @@ -16,7 +16,7 @@ console.log({ cacheMs: rollup.latest.cacheMs, }); -// there is only 1 commit, always index 0 +// there is only 1 commit const { prover: _, ...commit } = await rollup.fetchCommit(0n); console.log(commit); diff --git a/test/workarounds/polygon-proof-retry.test.ts b/test/workarounds/polygon-proof-retry.test.ts index 9c655ed5..b8743ce4 100755 --- a/test/workarounds/polygon-proof-retry.test.ts +++ b/test/workarounds/polygon-proof-retry.test.ts @@ -4,7 +4,7 @@ import { toPaddedHex } from '../../src/utils.js'; import { test, expect, afterAll } from 'bun:test'; import { describe } from '../bun-describe-fix.js'; import { CHAINS } from '../../src/chains.js'; -import { EthProver } from '../../src/index.js'; +import { EthProver } from '../../src/eth/EthProver.js'; import { Provider } from '../../src/types.js'; describe.skipIf(!!process.env.IS_CI)('polygon eth_getProof retry', async () => {