From 59f768fad7d08564500f00de2da4a97fa5b2a3f4 Mon Sep 17 00:00:00 2001 From: Torrey Atcitty Date: Thu, 10 Aug 2023 19:36:18 -0700 Subject: [PATCH] Move solc from optional to dev dependency and update Slueth interface to allow users to pass in solc.compile function. --- cli/sleuth.ts | 61 ++++++++++++++++++++++++++++++++++----------------- package.json | 12 +++++----- yarn.lock | 14 ++++++------ 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/cli/sleuth.ts b/cli/sleuth.ts index d3c4eff..716f3ee 100644 --- a/cli/sleuth.ts +++ b/cli/sleuth.ts @@ -7,7 +7,8 @@ import { parse } from '../parser/pkg/parser'; interface Opts { network?: string, - version?: number + version?: number, + solcCompileFn?: (jsonInput:string) => string }; const defaultOpts = { @@ -64,14 +65,19 @@ interface SolcOutput { errors?: string[], } -function solcCompile(input: SolcInput): SolcOutput { - let solc; - try { - solc = require('solc'); - } catch (e) { - throw new Error(`solc.js yarn dependency not found. Please build with optional dependencies included`); +function solcCompile( + input: SolcInput, + compileFn: ((input: string) => string) | undefined +): SolcOutput { + if (compileFn === undefined) { + throw new Error(`This option requires solc.compile() to be set in Opts or passed into as an arg to querySol(). Please ensure you are assigning solc.compile() and try again.`); } - return JSON.parse(solc.compile(JSON.stringify(input))); + + const inputJson = JSON.stringify(input); + if (inputJson == undefined) { + throw new Error(`Input not able to be compiled: ${input}`); + } + return JSON.parse(compileFn(inputJson)); } function hexify(v: string): string { @@ -85,19 +91,24 @@ export class Sleuth { sleuthAddr: string; sources: Source[]; coder: AbiCoder; + solcCompileFn: ((jsonInput: string) => string) | undefined; constructor(provider: Provider, opts: Opts = {}) { this.provider = provider; this.network = opts.network ?? defaultOpts.network; this.version = opts.version ?? defaultOpts.version; - this.sleuthAddr = getContractAddress({ from: sleuthDeployer, nonce: this.version - 1 }); + this.sleuthAddr = getContractAddress({ + from: sleuthDeployer, + nonce: this.version - 1, + }); this.sources = []; this.coder = new AbiCoder(); + this.solcCompileFn = opts.solcCompileFn; } query(q: string): Query { let registrations = this.sources.map((source) => { - let iface = JSON.stringify(source.iface.format(FormatTypes.full)); + let iface = JSON.stringify(source.iface.format(FormatTypes.full)); return `REGISTER CONTRACT ${source.name} AT ${source.address} WITH INTERFACE ${iface};` }).join("\n"); let fullQuery = `${registrations}${q}`; @@ -120,12 +131,12 @@ export class Sleuth { } }; - let result = solcCompile(input); + let result = solcCompile(input, this.solcCompileFn); console.log(result.contracts['query.yul']); if (result.errors && result.errors.length > 0) { throw new Error("Compilation Error: " + JSON.stringify(result.errors)); } - + let bytecode = result?.contracts['query.yul']?.Query?.evm?.bytecode?.object; if (!bytecode) { @@ -144,8 +155,12 @@ export class Sleuth { }; } - static querySol(q: string | object, opts: SolidityQueryOpts = {}): Query { - if (typeof(q) === 'string') { + static querySol( + q: string | object, + opts: SolidityQueryOpts = {}, + solcCompileFn: ((jsonInput: string) => string) | undefined + ): Query { + if (typeof q === 'string') { let r; try { // Try to parse as JSON, if that fails, then consider a query @@ -158,16 +173,18 @@ export class Sleuth { return this.querySolOutput(r, opts); } else { // This must be a source file, try to compile - return this.querySolSource(q, opts); + return this.querySolSource(q, opts, solcCompileFn); } - } else { // This was passed in as a pre-parsed contract. Or at least, it should have been. return this.querySolOutput(q as SolcContract, opts); } } - static querySolOutput(c: SolcContract, opts: SolidityQueryOpts = {}): Query { + static querySolOutput( + c: SolcContract, + opts: SolidityQueryOpts = {} + ): Query { let queryFunctionName = opts.queryFunctionName ?? 'query'; let b = c.evm?.bytecode?.object ?? c.bytecode?.object; if (!b) { @@ -185,7 +202,11 @@ export class Sleuth { }; } - static querySolSource(q: string, opts: SolidityQueryOpts = {}): Query { + static querySolSource( + q: string, + opts: SolidityQueryOpts = {}, + solcCompileFn: ((jsonInput: string) => string) | undefined + ): Query { let fnName = opts.queryFunctionName ?? 'query'; let input = { language: 'Solidity', @@ -203,7 +224,7 @@ export class Sleuth { } }; - let result = solcCompile(input); + let result = solcCompile(input, solcCompileFn); if (result.errors && result.errors.length > 0) { throw new Error("Compilation Error: " + JSON.stringify(result.errors)); } @@ -224,7 +245,7 @@ export class Sleuth { if (Array.isArray(iface)) { iface = new Interface(iface); } - this.sources.push({name, address, iface}); + this.sources.push({ name, address, iface }); } async fetch(q: Query, args?: A): Promise { diff --git a/package.json b/package.json index 25363bd..f998974 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,10 @@ "version": "1.0.1-alpha4", "main": "dist/index.js", "types": "dist/index.d.ts", - "files": ["dist/**/*", "parser/pkg/**/*"], + "files": [ + "dist/**/*", + "parser/pkg/**/*" + ], "repository": "https://github.com/compound-finance/sleuth", "author": "Geoffrey Hayes ", "license": "MIT", @@ -20,9 +23,8 @@ }, "dependencies": { "@ethersproject/contracts": "^5.7.0", - "@ethersproject/providers": "^5.7.2" + "@ethersproject/providers": "^5.7.2", + "solc": "^0.8.21" }, - "optionalDependencies": { - "solc": "^0.8.17" - } + "optionalDependencies": {} } diff --git a/yarn.lock b/yarn.lock index 740594b..a1df800 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2379,9 +2379,9 @@ resolve@^1.20.0: supports-preserve-symlinks-flag "^1.0.0" semver@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== semver@^6.0.0, semver@^6.3.0: version "6.3.0" @@ -2422,10 +2422,10 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -solc@^0.8.17: - version "0.8.17" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.17.tgz#c748fec6a64bf029ec406aa9b37e75938d1115ae" - integrity sha512-Dtidk2XtTTmkB3IKdyeg6wLYopJnBVxdoykN8oP8VY3PQjN16BScYoUJTXFm2OP7P0hXNAqWiJNmmfuELtLf8g== +solc@^0.8.21: + version "0.8.21" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.21.tgz#c3cd505c360ea2fa0eaa5ab574ef96bffb1a2766" + integrity sha512-N55ogy2dkTRwiONbj4e6wMZqUNaLZkiRcjGyeafjLYzo/tf/IvhHY5P5wpe+H3Fubh9idu071i8eOGO31s1ylg== dependencies: command-exists "^1.2.8" commander "^8.1.0"