diff --git a/.changeset/fluffy-cups-clap.md b/.changeset/fluffy-cups-clap.md new file mode 100644 index 0000000000..5e35281612 --- /dev/null +++ b/.changeset/fluffy-cups-clap.md @@ -0,0 +1,5 @@ +--- +"@nomiclabs/hardhat-vyper": patch +--- + +Added support for vyper settings 'evmVersion' and 'optimize' diff --git a/packages/hardhat-vyper/.mocharc.json b/packages/hardhat-vyper/.mocharc.json index d2b0c6d38f..b21e04d8b4 100644 --- a/packages/hardhat-vyper/.mocharc.json +++ b/packages/hardhat-vyper/.mocharc.json @@ -1,5 +1,5 @@ { "require": "ts-node/register/files", "ignore": ["test/fixture-projects/**/*"], - "timeout": 25000 + "timeout": 40000 } diff --git a/packages/hardhat-vyper/README.md b/packages/hardhat-vyper/README.md index 050a932cf7..dd421b6742 100644 --- a/packages/hardhat-vyper/README.md +++ b/packages/hardhat-vyper/README.md @@ -58,12 +58,23 @@ module.exports = { }; ``` -You can also configure multiple versions of the Vyper compiler: +You can also configure multiple versions of the Vyper compiler, as well as the compiler settings evmVersion and optimize. See the [Vyper docs](https://docs.vyperlang.org/en/v0.3.10/compiling-a-contract.html) for more info. ```js module.exports = { vyper: { - compilers: [{ version: "0.2.1" }, { version: "0.3.0" }], + compilers: [ + { + version: "0.2.1", + }, + { + version: "0.3.10", + settings: { + evmVersion: "paris", + optimize: "gas", + }, + }, + ], }, }; ``` diff --git a/packages/hardhat-vyper/src/compiler.ts b/packages/hardhat-vyper/src/compiler.ts index bf5f5b211f..7d529a6527 100644 --- a/packages/hardhat-vyper/src/compiler.ts +++ b/packages/hardhat-vyper/src/compiler.ts @@ -1,4 +1,7 @@ import { exec } from "child_process"; +import semver from "semver"; +import { VyperSettings } from "./types"; +import { VyperPluginError } from "./util"; export class Compiler { constructor(private _pathToVyper: string) {} @@ -6,11 +9,21 @@ export class Compiler { /** * * @param inputPaths array of paths to contracts to be compiled + * @param compilerVersion the version of the Vyper compiler + * @param settings the Vyper settings to use during compilation */ - public async compile(inputPaths: string[]) { + public async compile( + inputPaths: string[], + compilerVersion: string = "", + settings: VyperSettings = {} + ) { const output: string = await new Promise((resolve, reject) => { + const settingsCmd = getSettingsCmd(compilerVersion, settings); + const process = exec( - `${this._pathToVyper} -f combined_json ${inputPaths.join(" ")}`, + `${this._pathToVyper} ${settingsCmd} -f combined_json ${inputPaths.join( + " " + )}`, { maxBuffer: 1024 * 1024 * 500, }, @@ -28,3 +41,72 @@ export class Compiler { return JSON.parse(output); } } + +function getSettingsCmd( + compilerVersion: string, + settings: VyperSettings +): string { + let settingsStr = + settings.evmVersion !== undefined + ? `--evm-version ${settings.evmVersion} ` + : ""; + + settingsStr += getOptimize(compilerVersion, settings.optimize); + + return settingsStr; +} + +function getOptimize( + compilerVersion: string, + optimize: string | boolean | undefined +): string { + if (optimize === undefined) { + return ""; + } + + if (compilerVersion === "") { + throw new VyperPluginError( + "The 'compilerVersion' parameter must be set when the setting 'optimize' is set." + ); + } + + if (typeof optimize === "boolean") { + if (optimize) { + if ( + semver.gte(compilerVersion, "0.3.10") || + semver.lte(compilerVersion, "0.3.0") + ) { + throw new VyperPluginError( + `The 'optimize' setting with value 'true' is not supported for versions of the Vyper compiler older than or equal to 0.3.0 or newer than or equal to 0.3.10. You are currently using version ${compilerVersion}.` + ); + } + + // The optimizer is enabled by default + return ""; + } else { + if (semver.lte(compilerVersion, "0.3.0")) { + throw new VyperPluginError( + `The 'optimize' setting with value 'false' is not supported for versions of the Vyper compiler older than or equal to 0.3.0. You are currently using version ${compilerVersion}.` + ); + } + + return semver.lt(compilerVersion, "0.3.10") + ? "--no-optimize" + : "--optimize none"; + } + } + + if (typeof optimize === "string") { + if (semver.gte(compilerVersion, "0.3.10")) { + return `--optimize ${optimize}`; + } + + throw new VyperPluginError( + `The 'optimize' setting, when specified as a string value, is available only starting from the Vyper compiler version 0.3.10. You are currently using version ${compilerVersion}.` + ); + } + + throw new VyperPluginError( + `The 'optimize' setting has an invalid type value: ${typeof optimize}. Type should be either string or boolean.` + ); +} diff --git a/packages/hardhat-vyper/src/index.ts b/packages/hardhat-vyper/src/index.ts index 4692a5675e..e55c129cda 100644 --- a/packages/hardhat-vyper/src/index.ts +++ b/packages/hardhat-vyper/src/index.ts @@ -1,7 +1,7 @@ import type { Artifacts as ArtifactsImpl } from "hardhat/internal/artifacts"; import type { Artifacts } from "hardhat/types/artifacts"; import type { VyperFilesCache as VyperFilesCacheT } from "./cache"; -import type { VyperOutput, VyperBuild } from "./types"; +import type { VyperOutput, VyperBuild, VyperSettings } from "./types"; import type { ResolvedFile } from "./resolver"; import * as os from "os"; @@ -188,13 +188,21 @@ subtask(TASK_COMPILE_VYPER_RUN_BINARY) async ({ inputPaths, vyperPath, + vyperVersion, + settings, }: { inputPaths: string[]; vyperPath: string; + vyperVersion?: string; + settings?: VyperSettings; }): Promise => { const compiler = new Compiler(vyperPath); - const { version, ...contracts } = await compiler.compile(inputPaths); + const { version, ...contracts } = await compiler.compile( + inputPaths, + vyperVersion, + settings + ); return { version, @@ -249,36 +257,53 @@ subtask(TASK_COMPILE_VYPER) ({ version }) => version ); - const versionGroups: Record = {}; + const versionsToSettings = Object.fromEntries( + config.vyper.compilers.map(({ version, settings }) => [ + version, + settings, + ]) + ); + + const versionGroups: Record< + string, + { files: ResolvedFile[]; settings: VyperSettings } + > = {}; const unmatchedFiles: ResolvedFile[] = []; for (const file of resolvedFiles) { - const hasChanged = vyperFilesCache.hasFileChanged( - file.absolutePath, - file.contentHash, - { version: file.content.versionPragma } - ); - - if (!hasChanged) continue; - const maxSatisfyingVersion = semver.maxSatisfying( configuredVersions, file.content.versionPragma ); - // check if there are files that don't match any configured compiler - // version + // check if there are files that don't match any configured compiler version if (maxSatisfyingVersion === null) { unmatchedFiles.push(file); continue; } + const settings = versionsToSettings[maxSatisfyingVersion] ?? {}; + + const hasChanged = vyperFilesCache.hasFileChanged( + file.absolutePath, + file.contentHash, + { + version: maxSatisfyingVersion, + settings, + } + ); + + if (!hasChanged) continue; + if (versionGroups[maxSatisfyingVersion] === undefined) { - versionGroups[maxSatisfyingVersion] = [file]; + versionGroups[maxSatisfyingVersion] = { + files: [file], + settings, + }; continue; } - versionGroups[maxSatisfyingVersion].push(file); + versionGroups[maxSatisfyingVersion].files.push(file); } if (unmatchedFiles.length > 0) { @@ -297,7 +322,9 @@ ${list}` ); } - for (const [vyperVersion, files] of Object.entries(versionGroups)) { + for (const [vyperVersion, { files, settings }] of Object.entries( + versionGroups + )) { const vyperBuild: VyperBuild = await run(TASK_COMPILE_VYPER_GET_BUILD, { quiet, vyperVersion, @@ -312,6 +339,8 @@ ${list}` { inputPaths: files.map(({ absolutePath }) => absolutePath), vyperPath: vyperBuild.compilerPath, + vyperVersion, + settings, } ); @@ -329,7 +358,10 @@ ${list}` lastModificationDate: file.lastModificationDate.valueOf(), contentHash: file.contentHash, sourceName: file.sourceName, - vyperConfig: { version }, + vyperConfig: { + version, + settings, + }, versionPragma: file.content.versionPragma, artifacts: [artifact.contractName], }); diff --git a/packages/hardhat-vyper/src/types.ts b/packages/hardhat-vyper/src/types.ts index 8a17cd4c16..5eaad0b65d 100644 --- a/packages/hardhat-vyper/src/types.ts +++ b/packages/hardhat-vyper/src/types.ts @@ -1,7 +1,13 @@ export type VyperUserConfig = string | VyperConfig | MultiVyperConfig; +export interface VyperSettings { + evmVersion?: string; + optimize?: string | boolean; +} + export interface VyperConfig { version: string; + settings?: VyperSettings; } export interface MultiVyperConfig { diff --git a/packages/hardhat-vyper/test/fixture-projects/.gitignore b/packages/hardhat-vyper/test/fixture-projects/.gitignore index 1a65e437ab..64036ac854 100644 --- a/packages/hardhat-vyper/test/fixture-projects/.gitignore +++ b/packages/hardhat-vyper/test/fixture-projects/.gitignore @@ -1,2 +1,2 @@ -/*/cache -/*/artifacts +/**/cache +/**/artifacts diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-invalid-type/contracts/A.vy b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-invalid-type/contracts/A.vy new file mode 100644 index 0000000000..748ebc927a --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-invalid-type/contracts/A.vy @@ -0,0 +1,5 @@ +# @version 0.3.9 + +@external +def test() -> int128: + return 42 diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-invalid-type/hardhat.config.js b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-invalid-type/hardhat.config.js new file mode 100644 index 0000000000..e031582d90 --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-invalid-type/hardhat.config.js @@ -0,0 +1,15 @@ +require("../../../../src/index"); + +module.exports = { + vyper: { + compilers: [ + { + version: "0.3.9", + settings: { + evmVersion: "paris", + optimize: 12, + }, + }, + ], + }, +}; diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-new-versions/contracts/A.vy b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-new-versions/contracts/A.vy new file mode 100644 index 0000000000..2f6a0a54db --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-new-versions/contracts/A.vy @@ -0,0 +1,5 @@ +# @version 0.3.10 + +@external +def test() -> int128: + return 42 diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-new-versions/hardhat.config.js b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-new-versions/hardhat.config.js new file mode 100644 index 0000000000..e59e652644 --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-new-versions/hardhat.config.js @@ -0,0 +1,15 @@ +require("../../../../src/index"); + +module.exports = { + vyper: { + compilers: [ + { + version: "0.3.10", + settings: { + evmVersion: "paris", + optimize: false, + }, + }, + ], + }, +}; diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-old-versions-after-0.3.0/contracts/A.vy b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-old-versions-after-0.3.0/contracts/A.vy new file mode 100644 index 0000000000..748ebc927a --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-old-versions-after-0.3.0/contracts/A.vy @@ -0,0 +1,5 @@ +# @version 0.3.9 + +@external +def test() -> int128: + return 42 diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-old-versions-after-0.3.0/hardhat.config.js b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-old-versions-after-0.3.0/hardhat.config.js new file mode 100644 index 0000000000..a1f69ac41c --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-always-available-old-versions-after-0.3.0/hardhat.config.js @@ -0,0 +1,15 @@ +require("../../../../src/index"); + +module.exports = { + vyper: { + compilers: [ + { + version: "0.3.9", + settings: { + evmVersion: "paris", + optimize: false, + }, + }, + ], + }, +}; diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-not-available-old-versions/contracts/A.vy b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-not-available-old-versions/contracts/A.vy new file mode 100644 index 0000000000..14de3134ac --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-not-available-old-versions/contracts/A.vy @@ -0,0 +1,5 @@ +# @version 0.3.0 + +@external +def test() -> int128: + return 42 diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-not-available-old-versions/hardhat.config.js b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-not-available-old-versions/hardhat.config.js new file mode 100644 index 0000000000..4527da42e7 --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-false-not-available-old-versions/hardhat.config.js @@ -0,0 +1,15 @@ +require("../../../../src/index"); + +module.exports = { + vyper: { + compilers: [ + { + version: "0.3.0", + settings: { + evmVersion: "istanbul", + optimize: false, + }, + }, + ], + }, +}; diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-true/contracts/A.vy b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-true/contracts/A.vy new file mode 100644 index 0000000000..748ebc927a --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-true/contracts/A.vy @@ -0,0 +1,5 @@ +# @version 0.3.9 + +@external +def test() -> int128: + return 42 diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-true/hardhat.config.js b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-true/hardhat.config.js new file mode 100644 index 0000000000..965f42bb5a --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-set-to-true/hardhat.config.js @@ -0,0 +1,15 @@ +require("../../../../src/index"); + +module.exports = { + vyper: { + compilers: [ + { + version: "0.3.9", + settings: { + evmVersion: "paris", + optimize: true, + }, + }, + ], + }, +}; diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-string-not-available-old-versions/contracts/A.vy b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-string-not-available-old-versions/contracts/A.vy new file mode 100644 index 0000000000..748ebc927a --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-string-not-available-old-versions/contracts/A.vy @@ -0,0 +1,5 @@ +# @version 0.3.9 + +@external +def test() -> int128: + return 42 diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-string-not-available-old-versions/hardhat.config.js b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-string-not-available-old-versions/hardhat.config.js new file mode 100644 index 0000000000..a9eb741f4d --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-string-not-available-old-versions/hardhat.config.js @@ -0,0 +1,15 @@ +require("../../../../src/index"); + +module.exports = { + vyper: { + compilers: [ + { + version: "0.3.9", + settings: { + evmVersion: "paris", + optimize: "true", + }, + }, + ], + }, +}; diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-new-versions/contracts/A.vy b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-new-versions/contracts/A.vy new file mode 100644 index 0000000000..2f6a0a54db --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-new-versions/contracts/A.vy @@ -0,0 +1,5 @@ +# @version 0.3.10 + +@external +def test() -> int128: + return 42 diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-new-versions/hardhat.config.js b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-new-versions/hardhat.config.js new file mode 100644 index 0000000000..de9ea2595a --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-new-versions/hardhat.config.js @@ -0,0 +1,15 @@ +require("../../../../src/index"); + +module.exports = { + vyper: { + compilers: [ + { + version: "0.3.10", + settings: { + evmVersion: "paris", + optimize: true, + }, + }, + ], + }, +}; diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-old-versions/contracts/A.vy b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-old-versions/contracts/A.vy new file mode 100644 index 0000000000..14de3134ac --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-old-versions/contracts/A.vy @@ -0,0 +1,5 @@ +# @version 0.3.0 + +@external +def test() -> int128: + return 42 diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-old-versions/hardhat.config.js b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-old-versions/hardhat.config.js new file mode 100644 index 0000000000..1fa88e8c40 --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-settings-option-variants/optimize-true-not-available-old-versions/hardhat.config.js @@ -0,0 +1,15 @@ +require("../../../../src/index"); + +module.exports = { + vyper: { + compilers: [ + { + version: "0.3.0", + settings: { + evmVersion: "paris", + optimize: true, + }, + }, + ], + }, +}; diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-vyper-settings/contracts/A.vy b/packages/hardhat-vyper/test/fixture-projects/compilation-with-vyper-settings/contracts/A.vy new file mode 100644 index 0000000000..25f7f170c6 --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-vyper-settings/contracts/A.vy @@ -0,0 +1,5 @@ +# @version 0.3.8 + +@external +def test() -> int128: + return 42 diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-vyper-settings/contracts/B.vy b/packages/hardhat-vyper/test/fixture-projects/compilation-with-vyper-settings/contracts/B.vy new file mode 100644 index 0000000000..2f6a0a54db --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-vyper-settings/contracts/B.vy @@ -0,0 +1,5 @@ +# @version 0.3.10 + +@external +def test() -> int128: + return 42 diff --git a/packages/hardhat-vyper/test/fixture-projects/compilation-with-vyper-settings/hardhat.config.js b/packages/hardhat-vyper/test/fixture-projects/compilation-with-vyper-settings/hardhat.config.js new file mode 100644 index 0000000000..620d5eb0a2 --- /dev/null +++ b/packages/hardhat-vyper/test/fixture-projects/compilation-with-vyper-settings/hardhat.config.js @@ -0,0 +1,21 @@ +require("../../../src/index"); + +module.exports = { + vyper: { + compilers: [ + { + version: "0.3.10", + settings: { + evmVersion: "paris", + optimize: "gas", + }, + }, + { + version: "0.3.8", + settings: { + evmVersion: "shanghai", + }, + }, + ], + }, +}; diff --git a/packages/hardhat-vyper/test/tests.ts b/packages/hardhat-vyper/test/tests.ts index 04ac58d9ea..33e2409e20 100644 --- a/packages/hardhat-vyper/test/tests.ts +++ b/packages/hardhat-vyper/test/tests.ts @@ -5,6 +5,7 @@ import path from "path"; import { TASK_COMPILE } from "hardhat/builtin-tasks/task-names"; +import fs from "node:fs"; import { VYPER_FILES_CACHE_FILENAME } from "../src/constants"; import { useEnvironment, @@ -44,6 +45,179 @@ describe("Vyper plugin", function () { }); }); + describe("vyper settings", function () { + describe("compilation with different settings", function () { + useFixtureProject("compilation-with-vyper-settings"); + useEnvironment(); + + it("should compile and emit artifacts", async function () { + await this.env.run(TASK_COMPILE); + + assertFileExists(path.join("artifacts", "contracts", "A.vy", "A.json")); + assertFileExists(path.join("artifacts", "contracts", "B.vy", "B.json")); + }); + }); + + describe("optimize, as boolean type, can always be set to false in versions >= 0.3.10 (flag --optimize none)", function () { + useFixtureProject( + "compilation-with-settings-option-variants/optimize-set-to-false-always-available-new-versions" + ); + useEnvironment(); + + it("should compile successfully", async function () { + await this.env.run(TASK_COMPILE); + assertFileExists(path.join("artifacts", "contracts", "A.vy", "A.json")); + }); + }); + + describe("optimize, as boolean type, can always be set to false in versions 0.3.0 < v < 0.3.10 (flag --no-optimize)", function () { + useFixtureProject( + "compilation-with-settings-option-variants/optimize-set-to-false-always-available-old-versions-after-0.3.0" + ); + useEnvironment(); + + it("should compile successfully", async function () { + await this.env.run(TASK_COMPILE); + assertFileExists(path.join("artifacts", "contracts", "A.vy", "A.json")); + }); + }); + + describe("optimize, as boolean type, cannot be set to false in versions <= 0.3.0", function () { + useFixtureProject( + "compilation-with-settings-option-variants/optimize-set-to-false-not-available-old-versions" + ); + useEnvironment(); + + it("should fail the compilation", async function () { + await expect(this.env.run(TASK_COMPILE)).to.be.rejectedWith( + Error, + "The 'optimize' setting with value 'false' is not supported for versions of the Vyper compiler older than or equal to 0.3.0. You are currently using version 0.3.0." + ); + }); + }); + + describe("optimize setting set to true in supported versions", function () { + useFixtureProject( + "compilation-with-settings-option-variants/optimize-set-to-true" + ); + useEnvironment(); + + it("should compile successfully", async function () { + await this.env.run(TASK_COMPILE); + assertFileExists(path.join("artifacts", "contracts", "A.vy", "A.json")); + }); + }); + + describe("optimize set to true is not available for versions >= 0.3.10", function () { + useFixtureProject( + "compilation-with-settings-option-variants/optimize-true-not-available-new-versions" + ); + useEnvironment(); + + it("should fail the compilation", async function () { + await expect(this.env.run(TASK_COMPILE)).to.be.rejectedWith( + Error, + "The 'optimize' setting with value 'true' is not supported for versions of the Vyper compiler older than or equal to 0.3.0 or newer than or equal to 0.3.10. You are currently using version 0.3.10." + ); + }); + }); + + describe("optimize set to true is not available for versions <= 0.3.0", function () { + useFixtureProject( + "compilation-with-settings-option-variants/optimize-true-not-available-old-versions" + ); + useEnvironment(); + + it("should fail the compilation", async function () { + await expect(this.env.run(TASK_COMPILE)).to.be.rejectedWith( + Error, + "The 'optimize' setting with value 'true' is not supported for versions of the Vyper compiler older than or equal to 0.3.0 or newer than or equal to 0.3.10. You are currently using version 0.3.0." + ); + }); + }); + + describe("optimize setting cannot be a string for version < 0.3.10", function () { + useFixtureProject( + "compilation-with-settings-option-variants/optimize-string-not-available-old-versions" + ); + useEnvironment(); + + it("should fail the compilation", async function () { + await expect(this.env.run(TASK_COMPILE)).to.be.rejectedWith( + Error, + "The 'optimize' setting, when specified as a string value, is available only starting from the Vyper compiler version 0.3.10. You are currently using version 0.3.9." + ); + }); + }); + + describe("optimize setting must be a string or boolean type", function () { + useFixtureProject( + "compilation-with-settings-option-variants/optimize-invalid-type" + ); + useEnvironment(); + + it("should fail the compilation", async function () { + await expect(this.env.run(TASK_COMPILE)).to.be.rejectedWith( + Error, + "The 'optimize' setting has an invalid type value: number. Type should be either string or boolean." + ); + }); + }); + }); + + describe("caching mechanism", function () { + describe("caching mechanism without vyper settings", function () { + useFixtureProject("compilation-single-file"); + useEnvironment(); + + it("should not re-compile the contract because of the cache", async function () { + await this.env.run(TASK_COMPILE); + + const stats1 = fs.statSync( + path.join("artifacts", "contracts", "A.vy", "A.json") + ); + + // it should not compile again so the contract should not be modified + await this.env.run(TASK_COMPILE); + + const stats2 = fs.statSync( + path.join("artifacts", "contracts", "A.vy", "A.json") + ); + + assert.equal(stats1.mtimeMs, stats2.mtimeMs); + }); + }); + + describe("caching mechanism with vyper settings", function () { + useFixtureProject("compilation-with-vyper-settings"); + useEnvironment(); + + it("should not re-compile the contract because of the cache", async function () { + await this.env.run(TASK_COMPILE); + + const stats1A = fs.statSync( + path.join("artifacts", "contracts", "A.vy", "A.json") + ); + const stats1B = fs.statSync( + path.join("artifacts", "contracts", "B.vy", "B.json") + ); + + // it should not compile again so the contracts should not be modified + await this.env.run(TASK_COMPILE); + + const stats2A = fs.statSync( + path.join("artifacts", "contracts", "A.vy", "A.json") + ); + const stats2B = fs.statSync( + path.join("artifacts", "contracts", "B.vy", "B.json") + ); + + assert.equal(stats1A.mtimeMs, stats2A.mtimeMs); + assert.equal(stats1B.mtimeMs, stats2B.mtimeMs); + }); + }); + }); + describe("old versions of vyper", function () { useFixtureProject("old-vyper-versions");