#!/usr/bin/env bash set -euo pipefail ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd -P) # shellcheck source=process-lib.sh source "$ROOT/tools/process-lib.sh" remove_exact() { local path=$1 if [[ -e "$path" ]]; then rm -f -- "$path" printf 'Removed %s\n' "${path#"$ROOT/"}" fi } remove_local_manifest() { local path=$1 [[ -e "$path" ]] || return 0 if node -e 'const fs=require("fs"); const value=JSON.parse(fs.readFileSync(process.argv[1],"utf8")); process.exit(value && value.network === "anvil" && value.chainId === 31337 ? 0 : 1)' "$path" 2>/dev/null; then remove_exact "$path" else printf 'Preserved non-local or invalid manifest %s\n' "${path#"$ROOT/"}" fi } remove_local_upgrade_marker() { local path=$1 [[ -e "$path" ]] || return 0 if node -e ' const fs = require("fs"); const marker = JSON.parse(fs.readFileSync(process.argv[1], "utf8")); const record = (value) => value && typeof value === "object" && !Array.isArray(value); const exact = (value, keys) => record(value) && Object.keys(value).sort().join("\0") === [...keys].sort().join("\0"); const uint = (value) => Number.isSafeInteger(value) && value >= 0; const address = (value) => typeof value === "string" && /^0x[0-9a-fA-F]{40}$/.test(value) && !/^0x0{40}$/i.test(value); const same = (first, second) => address(first) && address(second) && first.toLowerCase() === second.toLowerCase(); const noop = exact(marker, ["mode", "chainId", "observedBlock", "ownerNonce", "proxy", "implementation"]) && marker.mode === "noop" && marker.chainId === 31337 && uint(marker.observedBlock) && uint(marker.ownerNonce) && address(marker.proxy) && address(marker.implementation); const upgradeKeys = ["mode", "network", "chainId", "token", "proxy", "previousImplementation", "implementation", "owner", "deploymentBlock", "snapshot"]; const snapshotKeys = ["proxy", "implementation", "owner", "asset", "paused", "balances", "liabilities", "reserves", "surplus", "deploymentBlock", "version"]; const snapshot = marker?.snapshot; const balances = Array.isArray(snapshot?.balances) && snapshot.balances.length > 0 && snapshot.balances.every((balance) => exact(balance, ["address", "balance"]) && address(balance.address) && uint(balance.balance)); const upgrade = exact(marker, upgradeKeys) && marker.mode === "upgrade" && marker.network === "anvil" && marker.chainId === 31337 && uint(marker.deploymentBlock) && marker.deploymentBlock >= 1 && [marker.token, marker.proxy, marker.previousImplementation, marker.implementation, marker.owner].every(address) && !same(marker.previousImplementation, marker.implementation) && exact(snapshot, snapshotKeys) && typeof snapshot.paused === "boolean" && snapshot.version === 1 && same(snapshot.proxy, marker.proxy) && same(snapshot.implementation, marker.previousImplementation) && same(snapshot.owner, marker.owner) && same(snapshot.asset, marker.token) && snapshot.deploymentBlock === marker.deploymentBlock && balances && uint(snapshot.liabilities) && uint(snapshot.reserves) && uint(snapshot.surplus) && snapshot.reserves >= snapshot.liabilities && snapshot.reserves - snapshot.liabilities === snapshot.surplus; process.exit(noop || upgrade ? 0 : 1); ' "$path" 2>/dev/null; then remove_exact "$path" else printf 'Preserved non-local or invalid upgrade marker %s\n' "${path#"$ROOT/"}" fi } demo_stop_recorded "$ROOT" vite demo_stop_recorded "$ROOT" anvil remove_exact "$ROOT/.demo/anvil.pid" remove_exact "$ROOT/.demo/anvil.start" remove_exact "$ROOT/.demo/anvil.pgid" remove_exact "$ROOT/.demo/anvil.log" remove_exact "$ROOT/.demo/vite.pid" remove_exact "$ROOT/.demo/vite.start" remove_exact "$ROOT/.demo/vite.pgid" remove_exact "$ROOT/.demo/vite.log" remove_local_manifest "$ROOT/deployments/pending.json" remove_local_upgrade_marker "$ROOT/deployments/upgrade-pending.json" remove_local_manifest "$ROOT/deployments/anvil.json" remove_local_manifest "$ROOT/deployments/active.json" remove_local_manifest "$ROOT/web/public/deployment.json" remove_exact "$ROOT/web/src/generated/contracts.ts" rmdir -- "$ROOT/.demo" 2>/dev/null || true printf '%s\n' 'Local generated state is reproducible with make demo-local.'