Source mirror · commit 369512f · 2026-10-26 · MIT · canonical repo: gitlab.com/jiapunk/upgrade-airlock
git clone https://upgrade-airlock.pages.dev/source/upgrade-airlock.git
upgrade-airlock / web / src / types.ts
web/src/types.ts61 lines · 2459 bytes
1// Demo implementations, rule ids and small number helpers shared by the whole app.
2import { keccak256, stringToBytes, type Hex } from 'viem'
3
4/** Implementations deployed by script/DeployEth.s.sol that the page recognises by address */
5export type CardId = 'evilMint' | 'evilOwner' | 'evilFee' | 'evilBaseFee' | 'evilDrain' | 'v2'
6export type ImplName = CardId | 'v1' | 'paused'
7export const IMPL_KEYS: readonly ImplName[] = ['v1', 'v2', 'evilMint', 'evilOwner', 'evilFee', 'evilBaseFee', 'evilDrain', 'paused']
8
9export interface CardInfo {
10 id: CardId
11 /** Contract name (a proper noun, never translated) */
12 name: string
13 expect: 'veto' | 'pass'
14 expectRule: RuleId | null
15}
16
17export const CARDS: CardInfo[] = [
18 { id: 'evilMint', name: 'EvilMint', expect: 'veto', expectRule: 'R1_TOTAL_SUPPLY' },
19 { id: 'evilOwner', name: 'EvilOwner', expect: 'veto', expectRule: 'R2_OWNER' },
20 { id: 'evilFee', name: 'EvilFee', expect: 'veto', expectRule: 'R3_TRANSFER_CONSERVATION' },
21 { id: 'evilBaseFee', name: 'EvilBaseFee', expect: 'veto', expectRule: 'R9_NEW_OPCODES' },
22 { id: 'evilDrain', name: 'EvilDrain', expect: 'veto', expectRule: 'R3B_THIRD_PARTY_FUNDS' },
23 { id: 'v2', name: 'DemoBTC v2', expect: 'pass', expectRule: null },
24]
25
26/** Rule ids of the CRE workflow; ruleHash = keccak256(utf8("GUARD/<ID>")), the bytes32 carried by Vetoed */
27export const RULE_IDS = [
28 'R1_TOTAL_SUPPLY',
29 'R2_OWNER',
30 'R3_TRANSFER_CONSERVATION',
31 'R3B_THIRD_PARTY_FUNDS',
32 'R4_TRANSFER_LIVENESS',
33 'R5_STRICT_CODEHASH',
34 'R6_SIM_FAILURE',
35 'R7_CONFIG_GUARD',
36 'R8_INIT_DATA',
37 'R9_NEW_OPCODES',
38] as const
39export type RuleId = (typeof RULE_IDS)[number]
40
41export const ruleHashOf = (id: string): Hex => keccak256(stringToBytes(`GUARD/${id}`))
42/** ruleHash (lowercase) -> rule id */
43export const RULE_BY_HASH = new Map<string, RuleId>(RULE_IDS.map((r) => [ruleHashOf(r).toLowerCase(), r]))
44
45/** "R1_TOTAL_SUPPLY" -> "R1" */
46export const ruleShort = (rule: string): string => rule.split('_')[0]
47
48export function toBig(x: unknown): bigint | null {
49 try {
50 if (x === null || x === undefined || x === '') return null
51 if (typeof x === 'bigint') return x
52 if (typeof x === 'number') return BigInt(Math.round(x))
53 if (typeof x === 'string') return BigInt(x)
54 } catch {
55 return null
56 }
57 return null
58}
59
60export const ZERO32 = ('0x' + '00'.repeat(32)) as Hex
61export const isZero32 = (h: string | null | undefined): boolean => !h || /^0x0*$/i.test(h)