diff --git a/modules/passkey/hardhat.config.ts b/modules/passkey/hardhat.config.ts index 0c549747a..2ec206cab 100644 --- a/modules/passkey/hardhat.config.ts +++ b/modules/passkey/hardhat.config.ts @@ -3,6 +3,7 @@ import dotenv from 'dotenv' import type { HardhatUserConfig } from 'hardhat/config' import 'hardhat-deploy' import { HttpNetworkUserConfig } from 'hardhat/types' +import './src/tasks/codesize' dotenv.config() const { CUSTOM_NODE_URL, MNEMONIC, ETHERSCAN_API_KEY, PK } = process.env diff --git a/modules/passkey/package.json b/modules/passkey/package.json index 4975f5817..87845bc14 100644 --- a/modules/passkey/package.json +++ b/modules/passkey/package.json @@ -31,6 +31,7 @@ "build:sol": "rimraf build typechain-types && hardhat compile", "build:ts": "rimraf dist && tsc", "coverage": "hardhat coverage", + "codesize": "hardhat codesize", "fmt": "prettier --write .", "fmt:check": "prettier --check .", "lint": "npm run lint:sol && npm run lint:ts", diff --git a/modules/passkey/src/tasks/codesize.ts b/modules/passkey/src/tasks/codesize.ts new file mode 100644 index 000000000..7e97daa16 --- /dev/null +++ b/modules/passkey/src/tasks/codesize.ts @@ -0,0 +1,37 @@ +import { task, types } from 'hardhat/config' +import { loadSolc } from '../utils/solc' + +task('codesize', 'Displays the codesize of the contracts') + .addParam('skipcompile', 'should not compile before printing size', false, types.boolean, true) + .addParam('contractname', 'name of the contract', undefined, types.string, true) + .setAction(async (taskArgs, hre) => { + if (!taskArgs.skipcompile) { + await hre.run('compile') + } + const contracts = await hre.artifacts.getAllFullyQualifiedNames() + for (const contract of contracts) { + const artifact = await hre.artifacts.readArtifact(contract) + if (taskArgs.contractname && taskArgs.contractname !== artifact.contractName) continue + console.log(artifact.contractName, hre.ethers.dataLength(artifact.deployedBytecode), 'bytes (limit is 24576)') + } + }) + +task('yulcode', 'Outputs yul code for contracts') + .addParam('contractname', 'name of the contract', undefined, types.string, true) + .setAction(async (taskArgs, hre) => { + const contracts = await hre.artifacts.getAllFullyQualifiedNames() + for (const contract of contracts) { + if (taskArgs.contractname && !contract.endsWith(taskArgs.contractname)) continue + const buildInfo = await hre.artifacts.getBuildInfo(contract) + if (!buildInfo) return + console.log({ buildInfo }) + buildInfo.input.settings.outputSelection['*']['*'].push('ir', 'evm.assembly') + const solcjs = await loadSolc(buildInfo.solcLongVersion) + const compiled = solcjs.compile(JSON.stringify(buildInfo.input)) + const output = JSON.parse(compiled) + console.log(output.contracts[contract.split(':')[0]]) + console.log(output.errors) + } + }) + +export {} diff --git a/modules/passkey/src/types/solc.d.ts b/modules/passkey/src/types/solc.d.ts new file mode 100644 index 000000000..02634bc7f --- /dev/null +++ b/modules/passkey/src/types/solc.d.ts @@ -0,0 +1,41 @@ +declare module 'solc' { + export interface CompilerInput { + language: string + sources: { + [fileName: string]: { + content: string + } + } + settings: { + outputSelection: { + [fileName: string]: { + [contractName: string]: string[] + } + } + } + } + + export interface CompilerOutput { + contracts: { + [fileName: string]: { + [contractName: string]: { + abi: any[] + evm: { + bytecode: { + object: string + } + } + } + } + } + sources: { + [fileName: string]: { + ast: any + } + } + } + + export function compile(input: string): string + + export function loadRemoteVersion(version: string, callback: (err: Error, solc: any) => void): void +} diff --git a/modules/passkey/src/utils/solc.ts b/modules/passkey/src/utils/solc.ts new file mode 100644 index 000000000..237b800fa --- /dev/null +++ b/modules/passkey/src/utils/solc.ts @@ -0,0 +1,18 @@ +import solc from 'solc' + +const solcCache: Record = {} + +export interface Compiler { + compile: (input: string) => string +} + +export const loadSolc = async (version: string): Promise => { + return await new Promise((resolve, reject) => { + if (solcCache[version] !== undefined) resolve(solcCache[version]) + else + solc.loadRemoteVersion(`v${version}`, (error: unknown, solcjs: Compiler) => { + solcCache[version] = solcjs + return error ? reject(error) : resolve(solcjs) + }) + }) +} diff --git a/modules/passkey/tsconfig.json b/modules/passkey/tsconfig.json index 5032b2fe0..e9c02a72c 100644 --- a/modules/passkey/tsconfig.json +++ b/modules/passkey/tsconfig.json @@ -8,5 +8,6 @@ "strict": true, "skipLibCheck": true, "resolveJsonModule": true - } + }, + "include": ["src/**/*.ts", "hardhat.config.ts", "test"] }