Last active
May 16, 2024 16:54
-
-
Save blmalone/1aedfec0e35af7690115125d251acf7e to your computer and use it in GitHub Desktop.
Define all L1 smart contracts version numbers for all optimism release tags (op-contracts/vX.Y.Z).
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
import * as https from "https"; | |
/** | |
* A mapping of smart contract names to their corresponding paths in the Optimism repository. | |
*/ | |
const CONTRACT_PATHS = { | |
AddressManager: "legacy/AddressManager", | |
AnchorStateRegistry: "dispute/AnchorStateRegistry", | |
DelayedWETH: "dispute/weth/DelayedWETH", | |
DisputeGameFactory: "dispute/DisputeGameFactory", | |
L1CrossDomainMessenger: "L1/L1CrossDomainMessenger", | |
L1ERC721Bridge: "L1/L1ERC721Bridge", | |
L1StandardBridge: "L1/L1StandardBridge", | |
L2OutputOracle: "L1/L2OutputOracle", | |
OptimismMintableERC20Factory: "universal/OptimismMintableERC20Factory", | |
OptimismPortal: "L1/OptimismPortal", | |
OptimismPortal2: "L1/OptimismPortal2", | |
SystemConfig: "L1/SystemConfig", | |
SuperchainConfig: "L1/SuperchainConfig", | |
ProtocolVersions: "L1/ProtocolVersions", | |
LivenessGuard: "Safe/LivenessGuard", | |
LivenessModule: "Safe/LivenessModule", | |
DeputyGuardianModule: "Safe/DeputyGuardianModule" | |
}; | |
/** | |
* Release tags to query for. | |
*/ | |
const TAGGED_VERSIONS = [ | |
"v1.0.0", | |
"v1.1.0", | |
"v1.2.0", | |
"v1.3.0", | |
"v1.4.0-rc.2", | |
"v1.4.0-rc.3", | |
"v1.4.0-rc.4", | |
"v1.5.0-rc.1" | |
]; | |
/** | |
* Smart contracts that were updated per op-contracts release tag (op-contracts/vX.Y.Z). | |
*/ | |
const CONTRACT_DELTAS = { | |
"v1.5.0-rc.1": { | |
...CONTRACT_PATHS | |
}, | |
"v1.4.0-rc.4": { | |
...CONTRACT_PATHS | |
}, | |
"v1.4.0-rc.3": { | |
...CONTRACT_PATHS | |
}, | |
"v1.4.0-rc.2": { | |
L2OutputOracle: CONTRACT_PATHS.L2OutputOracle, | |
OptimismPortal: CONTRACT_PATHS.OptimismPortal, | |
SystemConfig: CONTRACT_PATHS.SystemConfig, | |
DisputeGameFactory: CONTRACT_PATHS.DisputeGameFactory, | |
AnchorStateRegistry: CONTRACT_PATHS.AnchorStateRegistry, | |
DelayedWETH: CONTRACT_PATHS.DelayedWETH, | |
OptimismPortal2: CONTRACT_PATHS.OptimismPortal2 | |
}, | |
"v1.3.0": { | |
OptimismPortal: CONTRACT_PATHS.OptimismPortal, | |
L1CrossDomainMessenger: CONTRACT_PATHS.L1CrossDomainMessenger, | |
L1StandardBridge: CONTRACT_PATHS.L1StandardBridge, | |
L1ERC721Bridge: CONTRACT_PATHS.L1ERC721Bridge, | |
OptimismMintableERC20Factory: CONTRACT_PATHS.OptimismMintableERC20Factory, | |
L2OutputOracle: CONTRACT_PATHS.L2OutputOracle, | |
SystemConfig: CONTRACT_PATHS.SystemConfig | |
}, | |
"v1.2.0": { | |
...CONTRACT_PATHS | |
}, | |
"v1.1.0": { | |
ProtocolVersions: CONTRACT_PATHS.ProtocolVersions | |
}, | |
"v1.0.0": { | |
...CONTRACT_PATHS | |
} | |
}; | |
interface RequestOptions<T> { | |
method: "GET" | "POST"; | |
headers?: { [key: string]: string }; | |
data?: T; | |
} | |
function constructUrls(taggedVersion: string, contractPath: string): { rawUrl: string, url: string } { | |
const rawBaseUri = `https://raw.githubusercontent.com/ethereum-optimism/optimism/op-contracts/${taggedVersion}/packages/contracts-bedrock`; | |
const suffix = taggedVersion === "v1.0.0" ? "contracts" : "src"; | |
const baseUri = `https://github.com/ethereum-optimism/optimism/blob/op-contracts/${taggedVersion}/packages/contracts-bedrock`; | |
return { rawUrl: `${rawBaseUri}/${suffix}/${contractPath}.sol`, url: `${baseUri}/${suffix}/${contractPath}.sol` }; | |
} | |
async function makeRequest<T>(url: string, options: RequestOptions<T>): Promise<string> { | |
const { method, headers, data } = options; | |
const requestOptions: https.RequestOptions = { method, headers: headers || {} }; | |
return new Promise<string>((resolve, reject) => { | |
const req = https.request(url, requestOptions, res => { | |
let responseData = ""; | |
res.on("data", chunk => responseData += chunk); | |
res.on("end", () => resolve(responseData)); | |
}); | |
req.on("error", error => reject(error.message)); | |
if (method === "POST" && data) { | |
req.write(JSON.stringify(data)); | |
} | |
req.end(); | |
}); | |
} | |
async function fetchContract(url: string): Promise<string | undefined> { | |
try { | |
return makeRequest(url, { method: "GET", headers: {}, data: {} }); | |
} catch (error) { | |
console.error("Error fetching contract:", error); | |
return undefined; | |
} | |
} | |
function extractVersion(response: string, rawUrl: string, url: string, contractPath: string): { version: string, rawUrl: string, url: string } | undefined { | |
const lines = response.split("\n"); | |
const versionMatchRegex = /constant version = "(.*?)"/; | |
const semverMatchRegex = /\*\s*@custom:semver\s+([0-9]+\.[0-9]+\.[0-9]+)/; | |
for (let i = 0; i < lines.length; i++) { | |
const versionMatch = lines[i].match(versionMatchRegex); | |
if (versionMatch) { | |
return { version: versionMatch[1], rawUrl, url: `${url}#L${i}` }; | |
} | |
if (contractPath.includes("AddressManager")) { | |
return { version: "Latest", rawUrl, url }; | |
} | |
const semverMatch = lines[i].match(semverMatchRegex); | |
if (semverMatch) { | |
return { version: semverMatch[1], rawUrl, url: `${url}#L${++i}` }; | |
} | |
} | |
return undefined; | |
} | |
function removeBeforeSlash(input: string): string { | |
const index = input.lastIndexOf("/"); | |
return index !== -1 ? input.substring(index + 1) : input; | |
} | |
function makeLink(url: string, version: string): string { | |
return `\u001B]8;;${url}\u0007${version}\u001B]8;;\u0007`; // Using OSC 8 for hyperlinks in compatible terminals | |
} | |
async function main() { | |
const mapping = {}; | |
const tempMappingEntry = {}; | |
const consoleOutputEntry = {}; | |
for (const taggedVersion of TAGGED_VERSIONS) { | |
console.log(`\n##########\n${taggedVersion}\n##########`); | |
const contractsToCheck = CONTRACT_DELTAS[taggedVersion]; | |
for (const contractPath of Object.values(contractsToCheck) as string[]) { | |
const urls = constructUrls(taggedVersion, contractPath); | |
const data = await fetchContract(urls.rawUrl); | |
if (data) { | |
const versionInfo = extractVersion(data, urls.rawUrl, urls.url, contractPath); | |
if (versionInfo) { // if undefined, means contract live during this release tag. | |
consoleOutputEntry[removeBeforeSlash(contractPath)] = makeLink(versionInfo.url, versionInfo.version); | |
tempMappingEntry[removeBeforeSlash(contractPath)] = versionInfo.version; | |
} | |
} | |
} | |
Object.entries(consoleOutputEntry).forEach(([chainVersion, version]) => | |
console.log(`${chainVersion}: ${version}`) | |
); | |
mapping[taggedVersion] = JSON.parse(JSON.stringify(tempMappingEntry)); | |
} | |
// console.log(JSON.stringify(mapping)); | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment