-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8243 from ethereum-optimism/inphi/snapshots
feat(ctb): add storage-layout and method ABI snapshots
- Loading branch information
Showing
119 changed files
with
17,597 additions
and
0 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
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
136 changes: 136 additions & 0 deletions
136
packages/contracts-bedrock/scripts/generate-snapshots.ts
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,136 @@ | ||
import fs from 'fs' | ||
import path from 'path' | ||
|
||
const outdir = process.argv[2] || path.join(__dirname, '..', 'snapshots') | ||
const forgeArtifactsDir = path.join(__dirname, '..', 'forge-artifacts') | ||
|
||
const getAllContracts = (): Array<string> => { | ||
const paths = [] | ||
const readFilesRecursively = (dir: string) => { | ||
const files = fs.readdirSync(dir) | ||
|
||
for (const file of files) { | ||
const filePath = path.join(dir, file) | ||
const fileStat = fs.statSync(filePath) | ||
|
||
if (fileStat.isDirectory()) { | ||
readFilesRecursively(filePath) | ||
} else { | ||
paths.push(filePath) | ||
} | ||
} | ||
} | ||
readFilesRecursively(path.join(__dirname, '..', 'src')) | ||
|
||
// Assumes there is a single contract per file | ||
return paths | ||
.filter((x) => x.endsWith('.sol')) | ||
.map((p: string) => { | ||
const b = path.basename(p) | ||
return `${b}:${b.replace('.sol', '')}` | ||
}) | ||
.sort() | ||
} | ||
|
||
type AbiSpecStorageLayoutEntry = { | ||
label: string | ||
slot: number | ||
offset: number | ||
type: string | ||
bytes: number | ||
} | ||
const sortKeys = (obj: any) => { | ||
if (typeof obj !== 'object' || obj === null) { | ||
return obj | ||
} | ||
return Object.keys(obj) | ||
.sort() | ||
.reduce( | ||
(acc, key) => { | ||
acc[key] = sortKeys(obj[key]) | ||
return acc | ||
}, | ||
Array.isArray(obj) ? [] : {} | ||
) | ||
} | ||
|
||
const main = async () => { | ||
console.log(`writing abi spec to ${outdir}`) | ||
|
||
const storageLayoutDir = path.join(outdir, 'storageLayout') | ||
const abiDir = path.join(outdir, 'abi') | ||
fs.mkdirSync(storageLayoutDir, { recursive: true }) | ||
fs.mkdirSync(abiDir, { recursive: true }) | ||
|
||
const contracts = getAllContracts() | ||
|
||
for (const contract of contracts) { | ||
const toks = contract.split(':') | ||
const contractFile = contract.split(':')[0] | ||
const contractName = toks[1] | ||
|
||
let artifactFile = path.join( | ||
forgeArtifactsDir, | ||
contractFile, | ||
`${contractName}.json` | ||
) | ||
|
||
// NOTE: Read the first version in the directory. We may want to assert that all version's ABIs are identical | ||
if (!fs.existsSync(artifactFile)) { | ||
const filename = fs.readdirSync(path.dirname(artifactFile))[0] | ||
artifactFile = path.join(path.dirname(artifactFile), filename) | ||
} | ||
|
||
const data = fs.readFileSync(artifactFile) | ||
const artifact = JSON.parse(data.toString()) | ||
|
||
// ignore abstract contracts | ||
if (artifact.bytecode.object === '0x') { | ||
console.log(`ignoring interface ${contractName}`) | ||
continue | ||
} | ||
|
||
// HACK: This is a hack to ignore libraries. Not robust against changes to solc's internal ast repr | ||
const isContract = artifact.ast.nodes.some((node: any) => { | ||
return ( | ||
node.nodeType === 'ContractDefinition' && | ||
node.name === contractName && | ||
node.contractKind === 'contract' | ||
) | ||
}) | ||
if (!isContract) { | ||
console.log(`ignoring library/interface ${contractName}`) | ||
continue | ||
} | ||
|
||
const storageLayout: AbiSpecStorageLayoutEntry[] = [] | ||
for (const storageEntry of artifact.storageLayout.storage) { | ||
// convert ast-based type to solidity type | ||
const typ = artifact.storageLayout.types[storageEntry.type] | ||
if (typ === undefined) { | ||
throw new Error( | ||
`undefined type for ${contractName}:${storageEntry.label}` | ||
) | ||
} | ||
storageLayout.push({ | ||
label: typ.label, | ||
bytes: typ.numberOfBytes, | ||
offset: storageEntry.offset, | ||
slot: storageEntry.slot, | ||
type: storageEntry.type, | ||
}) | ||
} | ||
|
||
// Sort snapshots for easier manual inspection | ||
fs.writeFileSync( | ||
`${abiDir}/${contractName}.json`, | ||
JSON.stringify(sortKeys(artifact.abi), null, 2) | ||
) | ||
fs.writeFileSync( | ||
`${storageLayoutDir}/${contractName}.json`, | ||
JSON.stringify(sortKeys(storageLayout), null, 2) | ||
) | ||
} | ||
} | ||
|
||
main() |
116 changes: 116 additions & 0 deletions
116
packages/contracts-bedrock/snapshots/abi/AddressManager.json
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,116 @@ | ||
[ | ||
{ | ||
"anonymous": false, | ||
"inputs": [ | ||
{ | ||
"indexed": true, | ||
"internalType": "string", | ||
"name": "name", | ||
"type": "string" | ||
}, | ||
{ | ||
"indexed": false, | ||
"internalType": "address", | ||
"name": "newAddress", | ||
"type": "address" | ||
}, | ||
{ | ||
"indexed": false, | ||
"internalType": "address", | ||
"name": "oldAddress", | ||
"type": "address" | ||
} | ||
], | ||
"name": "AddressSet", | ||
"type": "event" | ||
}, | ||
{ | ||
"anonymous": false, | ||
"inputs": [ | ||
{ | ||
"indexed": true, | ||
"internalType": "address", | ||
"name": "previousOwner", | ||
"type": "address" | ||
}, | ||
{ | ||
"indexed": true, | ||
"internalType": "address", | ||
"name": "newOwner", | ||
"type": "address" | ||
} | ||
], | ||
"name": "OwnershipTransferred", | ||
"type": "event" | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "string", | ||
"name": "_name", | ||
"type": "string" | ||
} | ||
], | ||
"name": "getAddress", | ||
"outputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "", | ||
"type": "address" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "owner", | ||
"outputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "", | ||
"type": "address" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "renounceOwnership", | ||
"outputs": [], | ||
"stateMutability": "nonpayable", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "string", | ||
"name": "_name", | ||
"type": "string" | ||
}, | ||
{ | ||
"internalType": "address", | ||
"name": "_address", | ||
"type": "address" | ||
} | ||
], | ||
"name": "setAddress", | ||
"outputs": [], | ||
"stateMutability": "nonpayable", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "newOwner", | ||
"type": "address" | ||
} | ||
], | ||
"name": "transferOwnership", | ||
"outputs": [], | ||
"stateMutability": "nonpayable", | ||
"type": "function" | ||
} | ||
] |
90 changes: 90 additions & 0 deletions
90
packages/contracts-bedrock/snapshots/abi/AdminFaucetAuthModule.json
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,90 @@ | ||
[ | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "_admin", | ||
"type": "address" | ||
}, | ||
{ | ||
"internalType": "string", | ||
"name": "_name", | ||
"type": "string" | ||
}, | ||
{ | ||
"internalType": "string", | ||
"name": "_version", | ||
"type": "string" | ||
} | ||
], | ||
"stateMutability": "nonpayable", | ||
"type": "constructor" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "ADMIN", | ||
"outputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "", | ||
"type": "address" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "PROOF_TYPEHASH", | ||
"outputs": [ | ||
{ | ||
"internalType": "bytes32", | ||
"name": "", | ||
"type": "bytes32" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"components": [ | ||
{ | ||
"internalType": "address payable", | ||
"name": "recipient", | ||
"type": "address" | ||
}, | ||
{ | ||
"internalType": "bytes32", | ||
"name": "nonce", | ||
"type": "bytes32" | ||
} | ||
], | ||
"internalType": "struct Faucet.DripParameters", | ||
"name": "_params", | ||
"type": "tuple" | ||
}, | ||
{ | ||
"internalType": "bytes32", | ||
"name": "_id", | ||
"type": "bytes32" | ||
}, | ||
{ | ||
"internalType": "bytes", | ||
"name": "_proof", | ||
"type": "bytes" | ||
} | ||
], | ||
"name": "verify", | ||
"outputs": [ | ||
{ | ||
"internalType": "bool", | ||
"name": "valid_", | ||
"type": "bool" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
} | ||
] |
Oops, something went wrong.