Skip to content

Commit

Permalink
Add support for custom solc versions (#11)
Browse files Browse the repository at this point in the history
* Add support for custom solc versions

If the required version of solc isn't currently in use solc will
[1](download the required version of itself). Normally you can pass
"version" in the the truffle config to trigger this behavior but our
truffle version field is already filled with a path to our custom solc
compiler. Instead we pass the enviroment variable `SOLC_VERSION` which
triggers it.

Truffle expects `compile` to be synchronous so we can't do anything
asynchronous in that function. To get around this we use `execSync` which
executes synchronously.

[1]: https://github.com/ethereum/solc-js/blob/5c1280ca2c73dfba58bad21849b16eb1fa5618e5/README.md#using-a-legacy-version
  • Loading branch information
masonforest authored Feb 20, 2020
1 parent 0df35d9 commit bbca409
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 4 deletions.
1 change: 1 addition & 0 deletions packages/solc-transpiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"dependencies": {
"@eth-optimism/core-utils": "~0.0.1-alpha.7",
"@eth-optimism/rollup-dev-tools": "~0.0.1-alpha.7",
"require-from-string": "^2.0.2",
"solc": "^0.5.12"
},
"devDependencies": {
Expand Down
67 changes: 64 additions & 3 deletions packages/solc-transpiler/src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
remove0x,
} from '@eth-optimism/core-utils'
import * as solc from 'solc'
import { execSync } from 'child_process'
import * as requireFromString from 'require-from-string'

const log: Logger = getLogger('solc-transpiler')

Expand All @@ -36,14 +38,15 @@ interface TranspilationOutput {
* @returns The Solc output as a string.
*/
export const compile = (configJsonString: string, callbacks?: any): string => {
const compiler = getCompiler(process.env.SOLC_VERSION)
log.debug(`Trying to transpile with config: ${configJsonString}`)
let json: any
try {
json = JSON.parse(configJsonString)
} catch (e) {
log.debug(`Cannot parse JSON: ${JSON.stringify(e)}`)
// todo: populate some errors
return solc.compile(configJsonString)
return compiler.compile(configJsonString)
}

const inputErrors: string = getInputErrors(json)
Expand All @@ -53,8 +56,8 @@ export const compile = (configJsonString: string, callbacks?: any): string => {

const solcConfig: string = getSolcConfig(json)
const resString = !!callbacks
? solc.compile(solcConfig, callbacks)
: solc.compile(solcConfig)
? compiler.compile(solcConfig, callbacks)
: compiler.compile(solcConfig)

const res = JSON.parse(resString)
if (
Expand Down Expand Up @@ -110,6 +113,64 @@ export const compile = (configJsonString: string, callbacks?: any): string => {
return formatOutput(res, json)
}

/**
* Gets the requested version of the solc module. solc-js provides downloadable
* versions of itself which can be downloaded and used to compile contracts that
* require different compiler versions. This function must be synchronous so it
* can be used in the compilation process which is also synchronous. To achieve
* this we construct a string of JavaScript which downloads the latest version
* of solc and run that code using `execSync`
*
* @param versionString The requested version of solc
* @returns The requested version of the `solc` module or the latest version
*/
const getCompiler = (versionString: string): typeof solc => {
if (!versionString) {
return solc
}

const getCompilerString = `
function httpsRequest(params, postData) {
return new Promise(function(resolve, reject) {
var req = https.request(params, function(res) {
var body = [];
res.on("data", function(chunk) {
body.push(chunk);
});
res.on("end", function() {
try {
body = Buffer.concat(body).toString();
} catch(e) {
reject(e);
}
resolve(body);
});
});
req.on("error", function(err) {
reject(err);
});
req.end();
});
}
async function getSolcVersion(versionString) {
const listUrl = "https://ethereum.github.io/solc-bin/bin/list.json";
const {releases} = JSON.parse(await httpsRequest(listUrl))
const solcUrl = "https://ethereum.github.io/solc-bin/bin/" + releases[versionString];
return await httpsRequest(solcUrl);
}
(async () => {
await process.stdout.write(await getSolcVersion("${versionString}"));
})();
`
return solc.setupMethods(
requireFromString(
execSync(`${process.argv[0]} -e '${getCompilerString}'`).toString()
)
)
}

const getExecutionManagerAddress = (configObject: any): string => {
return (
configObject.settings.executionManagerAddress ||
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8906,7 +8906,7 @@ require-directory@^2.1.1:
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=

require-from-string@^2.0.0:
require-from-string@^2.0.0, require-from-string@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
Expand Down

0 comments on commit bbca409

Please sign in to comment.