Skip to content

Commit

Permalink
ci: PR tests (#10)
Browse files Browse the repository at this point in the history
* ci: initial test pass

* ci: initial test pass

* ci: add botched data file

* ci: add botched data file

* ci: test

* ci: test

* ci: test

* ci: test

* ci: test

* ci: should fail

* ci: should also fail

* ci: done
  • Loading branch information
AlexBHarley authored Apr 16, 2024
1 parent 514aa33 commit ba88a32
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 5 deletions.
18 changes: 14 additions & 4 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
name: CI

on: [push]
on:
pull_request:
branches: main

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "20.x"

- uses: pnpm/action-setup@v3
with:
version: 8
run_install: true
# - run: npm ci
# - run: npm run build --if-present
- run: npm test

- name: Get changes
run: git diff --name-only -r HEAD^1 HEAD

- name: Test
run: |
npx tsx ./src/verify.ts $(git diff --name-only -r HEAD^1 HEAD)
2 changes: 1 addition & 1 deletion data/APU/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
"1": "0x594DaaD7D77592a2b97b725A7AD59D7E188b5bFa",
"8453": "0x7A2C5e7788E55Ec0a7ba4aEeC5B3da322718Fb5e"
}
}
}
36 changes: 36 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as viemChains from "viem/chains";

export interface SuperchainToken {
chainId: number;
address: string;
name: string;
symbol: string;
decimals: number;
logoURI: string;
extensions: {
standardBridgeAddresses: {
[chainId: string]: string;
};
opTokenId: string;
};
}

export interface TokenData {
name: string;
symbol: string;
decimals: number;
logoURI: string;
opTokenId: string;
addresses: {
[chainId: string]: string;
};
}

export const getViemChain = (id: number | string) => {
const chainId = typeof id === "string" ? parseInt(id) : id;
const chain = Object.values(viemChains).find((x) => x.id === chainId);
if (!chain) {
throw new Error(`Chain ${id} not found`);
}
return chain;
};
119 changes: 119 additions & 0 deletions src/verify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { readFileSync } from "fs";
import { join } from "path";
import { Address, createPublicClient, http } from "viem";
import { isAddressEqual, isAddress } from "viem/utils";

import { OptimismMintableERC20Abi } from "./abis/OptimismMintableERC20";
import { StandardBridgeAbi } from "./abis/StandardBridge";
import { getViemChain, TokenData } from "./utils";

async function main() {
const [, , ...files] = process.argv;

for (const path of files) {
if (!path.startsWith("data") || !path.endsWith(".json")) {
continue;
}

let data: TokenData | null = null;
try {
data = JSON.parse(readFileSync(join(__dirname, "..", path)).toString());
} catch {
throw new Error(`Invalid JSON at ${path}`);
}

console.log("Verifying", data!.name);

let mintable = false;
let base = false;

for (const [chainId, address] of Object.entries(data!.addresses)) {
const client = createPublicClient({
chain: getViemChain(chainId),
transport: http(),
});

if (!isAddress(address)) {
throw new Error(`Invalid address for chainId ${chainId}`);
}

const [BRIDGE, REMOTE_TOKEN] = await Promise.all([
client
.readContract({
abi: OptimismMintableERC20Abi,
functionName: "BRIDGE",
address: address as Address,
})
.catch(() => null),
client
.readContract({
abi: OptimismMintableERC20Abi,
functionName: "REMOTE_TOKEN",
address: address as Address,
})
.catch(() => null),
]);
console.log("BRIDGE", BRIDGE);
console.log("REMOTE_TOKEN", REMOTE_TOKEN);

// mintable
if (BRIDGE && REMOTE_TOKEN) {
mintable = true;
console.log(chainId, "is mintable");

const baseChainId = Object.entries(data!.addresses).find(
([_, address]) => isAddressEqual(address as Address, REMOTE_TOKEN)
);
if (!baseChainId) {
throw new Error(
`No corresponding token address found for ${
data!.symbol
} on ${chainId}`
);
}

const baseClient = createPublicClient({
chain: getViemChain(baseChainId[0]),
transport: http(),
});

const BASE_BRIDGE = await client
.readContract({
abi: StandardBridgeAbi,
functionName: "OTHER_BRIDGE",
address: BRIDGE,
})
.catch(() => null);
if (!BASE_BRIDGE) {
throw new Error("BASE_BRIDGE not found");
}
console.log("BASE_BRIDGE", BASE_BRIDGE);

const REMOTE_BRIDGE = await baseClient
.readContract({
abi: StandardBridgeAbi,
functionName: "OTHER_BRIDGE",
address: BASE_BRIDGE,
})
.catch(() => null);
console.log("REMOTE_BRIDGE", REMOTE_BRIDGE);

if (!REMOTE_BRIDGE) {
throw new Error("REMOTE_BRIDGE not found");
}
if (!isAddressEqual(REMOTE_BRIDGE, BRIDGE)) {
throw new Error("Bridge addresses do not match");
}
} else {
base = true;
}
}

if (mintable !== true || base !== true) {
throw new Error("Tokens do not point at each other");
} else {
console.log("✅");
}
}
}
main();

0 comments on commit ba88a32

Please sign in to comment.