|
| 1 | +import { describe, it, expect } from "vitest"; |
| 2 | +import { |
| 3 | + CHAIN_IDS, |
| 4 | + CHAIN_ID_TO_NAME, |
| 5 | + SUPPORTED_CHAINS, |
| 6 | +} from "../src/types/index.js"; |
| 7 | +import { CONTRACTS, NATIVE_SYMBOL } from "../src/config/contracts.js"; |
| 8 | +import { VIEM_CHAINS } from "../src/config/chains.js"; |
| 9 | + |
| 10 | +/** |
| 11 | + * Invariants for Optimism (chainId 10) — mirrors base-chain-support.test.ts. |
| 12 | + * Locks the chain registration so removing Optimism requires intentional |
| 13 | + * deletion of this suite rather than a silent refactor of one of the |
| 14 | + * Record<SupportedChain, …> tables. |
| 15 | + */ |
| 16 | +describe("Optimism chain registration", () => { |
| 17 | + it("is listed in SUPPORTED_CHAINS", () => { |
| 18 | + expect(SUPPORTED_CHAINS).toContain("optimism"); |
| 19 | + }); |
| 20 | + |
| 21 | + it("maps to chainId 10 in both directions", () => { |
| 22 | + expect(CHAIN_IDS.optimism).toBe(10); |
| 23 | + expect(CHAIN_ID_TO_NAME[10]).toBe("optimism"); |
| 24 | + }); |
| 25 | + |
| 26 | + it("uses ETH as its native symbol", () => { |
| 27 | + expect(NATIVE_SYMBOL.optimism).toBe("ETH"); |
| 28 | + }); |
| 29 | + |
| 30 | + it("has a viem Chain registered with matching chainId", () => { |
| 31 | + expect(VIEM_CHAINS.optimism).toBeDefined(); |
| 32 | + expect(VIEM_CHAINS.optimism.id).toBe(10); |
| 33 | + }); |
| 34 | +}); |
| 35 | + |
| 36 | +describe("Optimism contract addresses", () => { |
| 37 | + const optimismContracts = CONTRACTS.optimism; |
| 38 | + |
| 39 | + it("includes Aave V3 deployment triple (provider + uiPoolDataProvider + pool)", () => { |
| 40 | + expect(optimismContracts.aave.poolAddressProvider).toMatch(/^0x[a-fA-F0-9]{40}$/); |
| 41 | + expect(optimismContracts.aave.uiPoolDataProvider).toMatch(/^0x[a-fA-F0-9]{40}$/); |
| 42 | + expect(optimismContracts.aave.pool).toMatch(/^0x[a-fA-F0-9]{40}$/); |
| 43 | + }); |
| 44 | + |
| 45 | + it("pins the Aave V3 Pool to the canonical Optimism deployment", () => { |
| 46 | + // Used by pre-sign-check.ts as the allowlist entry for Aave txs on |
| 47 | + // Optimism. Hard-pin so a refactor can't silently swap it for an attacker |
| 48 | + // contract. Sourced from bgd-labs/aave-address-book AaveV3Optimism.sol. |
| 49 | + expect(optimismContracts.aave.pool).toBe("0x794a61358D6845594F94dc1DB02A252b5b4814aD"); |
| 50 | + }); |
| 51 | + |
| 52 | + it("uses the canonical cross-chain Uniswap V3 deployment (not Base's chain-specific one)", () => { |
| 53 | + // Optimism follows the standard Uniswap V3 addresses shared across |
| 54 | + // Ethereum/Arbitrum/Polygon. Only Base diverged. Pin both factory and |
| 55 | + // SwapRouter02 so a copy-paste from the Base block fails this assertion. |
| 56 | + expect(optimismContracts.uniswap.factory).toBe( |
| 57 | + "0x1F98431c8aD98523631AE4a59f267346ea31F984" |
| 58 | + ); |
| 59 | + expect(optimismContracts.uniswap.swapRouter02).toBe( |
| 60 | + "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45" |
| 61 | + ); |
| 62 | + }); |
| 63 | + |
| 64 | + it("includes Compound V3 USDC + WETH + USDT markets", () => { |
| 65 | + expect(optimismContracts.compound.cUSDCv3).toBe( |
| 66 | + "0x2e44e174f7D53F0212823acC11C01A11d58c5bCB" |
| 67 | + ); |
| 68 | + expect(optimismContracts.compound.cWETHv3).toBe( |
| 69 | + "0xE36A30D249f7761327fd973001A32010b521b6Fd" |
| 70 | + ); |
| 71 | + expect(optimismContracts.compound.cUSDTv3).toBe( |
| 72 | + "0x995E394b8B2437aC8Ce61Ee0bC610D617962B214" |
| 73 | + ); |
| 74 | + }); |
| 75 | + |
| 76 | + it("exposes the OP-stack predeploy WETH + native USDC + OP token", () => { |
| 77 | + expect(optimismContracts.tokens.WETH).toBe("0x4200000000000000000000000000000000000006"); |
| 78 | + expect(optimismContracts.tokens.USDC).toBe("0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"); |
| 79 | + expect(optimismContracts.tokens.OP).toBe("0x4200000000000000000000000000000000000042"); |
| 80 | + }); |
| 81 | + |
| 82 | + it("does NOT register Lido or EigenLayer (L1-only protocols)", () => { |
| 83 | + expect((optimismContracts as Record<string, unknown>).lido).toBeUndefined(); |
| 84 | + expect((optimismContracts as Record<string, unknown>).eigenlayer).toBeUndefined(); |
| 85 | + }); |
| 86 | + |
| 87 | + it("does NOT register Morpho Blue (deferred — discovery block unverified)", () => { |
| 88 | + // Morpho Blue is deployed on Optimism, but the discovery scan in |
| 89 | + // src/modules/morpho/discover.ts requires a known deployment block. |
| 90 | + // Same tripwire as Base. |
| 91 | + expect((optimismContracts as Record<string, unknown>).morpho).toBeUndefined(); |
| 92 | + }); |
| 93 | +}); |
0 commit comments