-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 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
1 parent
514aa33
commit ba88a32
Showing
4 changed files
with
170 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,4 @@ | |
"1": "0x594DaaD7D77592a2b97b725A7AD59D7E188b5bFa", | ||
"8453": "0x7A2C5e7788E55Ec0a7ba4aEeC5B3da322718Fb5e" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |