From 6465e57ab177c7905c4094fb82061d1561c6f37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Tue, 10 Sep 2024 17:38:55 +0200 Subject: [PATCH 1/5] feat: enhance writeMastercopy* functions --- src/artifact/writeMastercopyFromBuild.ts | 4 +++- src/artifact/writeMastercopyFromExplorer.ts | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/artifact/writeMastercopyFromBuild.ts b/src/artifact/writeMastercopyFromBuild.ts index 114c7c2..964350a 100644 --- a/src/artifact/writeMastercopyFromBuild.ts +++ b/src/artifact/writeMastercopyFromBuild.ts @@ -49,7 +49,7 @@ export default function writeMastercopyFromBuild({ compilerInput?: any; buildDirPath?: string; mastercopyArtifactsFile?: string; -}) { +}): MastercopyArtifact { const buildArtifact = getBuildArtifact(contractName, buildDirPath); const mastercopies = existsSync(mastercopyArtifactsFile) @@ -111,4 +111,6 @@ export default function writeMastercopyFromBuild({ JSON.stringify(sortedMastercopies, null, 2), "utf8" ); + + return mastercopyArtifact; } diff --git a/src/artifact/writeMastercopyFromExplorer.ts b/src/artifact/writeMastercopyFromExplorer.ts index dad8bcc..51d17c8 100644 --- a/src/artifact/writeMastercopyFromExplorer.ts +++ b/src/artifact/writeMastercopyFromExplorer.ts @@ -106,4 +106,6 @@ export default async function writeMastercopyFromExplorer({ JSON.stringify(sortedMastercopies, null, 2), "utf8" ); + + return mastercopyArtifact; } From 627dde8b57c90dd4edab151f834b43ee7b904db1 Mon Sep 17 00:00:00 2001 From: juliopavila Date: Wed, 11 Sep 2024 11:36:07 -0300 Subject: [PATCH 2/5] Fix: Add library references to mastercopy JSON in Zodiac Core - Resolved issue where 'zodiac-core' was not including library references in the mastercopy artifacts. - Implemented logic to add 'libraries' field to the compilerInput in mastercopy artifacts. - Ensured correct linkage of deployed library addresses during the build process. --- src/artifact/writeMastercopyFromBuild.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/artifact/writeMastercopyFromBuild.ts b/src/artifact/writeMastercopyFromBuild.ts index 964350a..13d3beb 100644 --- a/src/artifact/writeMastercopyFromBuild.ts +++ b/src/artifact/writeMastercopyFromBuild.ts @@ -66,6 +66,23 @@ export default function writeMastercopyFromBuild({ mastercopies ); + const compilerInput = minimalCompilerInput || buildArtifact.compilerInput; + compilerInput.settings = compilerInput.settings || {}; + compilerInput.settings.libraries = compilerInput.settings.libraries || {}; + for (const libraryPath of Object.keys(buildArtifact.linkReferences)) { + compilerInput.settings.libraries[libraryPath] = + compilerInput.settings.libraries[libraryPath] || {}; + for (const libraryName of Object.keys( + buildArtifact.linkReferences[libraryPath] + )) { + const libraryAddress = + mastercopies[libraryName]?.[contractVersion]?.address; + if (libraryAddress) { + compilerInput.settings.libraries[libraryPath][libraryName] = + libraryAddress; + } + } + } const mastercopyArtifact: MastercopyArtifact = { contractName, sourceName: buildArtifact.sourceName, @@ -82,7 +99,7 @@ export default function writeMastercopyFromBuild({ constructorArgs, salt, abi: buildArtifact.abi, - compilerInput: minimalCompilerInput || buildArtifact.compilerInput, + compilerInput, }; const nextMastercopies = { From a9524e94400d3f312bd3ee31a92b3bb6c541465d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Fri, 13 Sep 2024 12:27:02 +0200 Subject: [PATCH 3/5] refactor: move linking code into its own function --- src/artifact/internal/getBuildArtifact.ts | 62 ---------- src/artifact/internal/linkBuildArtifact.ts | 127 +++++++++++++++++++++ src/artifact/writeMastercopyFromBuild.ts | 37 ++---- 3 files changed, 137 insertions(+), 89 deletions(-) create mode 100644 src/artifact/internal/linkBuildArtifact.ts diff --git a/src/artifact/internal/getBuildArtifact.ts b/src/artifact/internal/getBuildArtifact.ts index 2781c65..e24e6f7 100644 --- a/src/artifact/internal/getBuildArtifact.ts +++ b/src/artifact/internal/getBuildArtifact.ts @@ -40,68 +40,6 @@ export default function getBuildArtifact( }; } -/** - * Replaces library references in the bytecode with actual deployed addresses. - * - * This function scans the bytecode and replaces placeholder references - * to libraries with their actual on-chain addresses. It ensures that - * the library addresses are valid and properly formatted. - * - * @param {string} bytecode - The bytecode that may contain library references. - * @param {Record} linkReferences - References to libraries, as returned by the compiler. - * @param {Record} libraryAddresses - A map of library names to their deployed addresses. - * @returns {string} - The updated bytecode with library references replaced by actual addresses. - * - * @throws {Error} - Throws if a library address is missing or incorrectly formatted. - */ -export function resolveLinksInBytecode( - contractVersion: string, - artifact: BuildArtifact, - mastercopies: Record> -): string { - let bytecode = artifact.bytecode; - - for (const libraryPath of Object.keys(artifact.linkReferences)) { - for (const libraryName of Object.keys( - artifact.linkReferences[libraryPath] - )) { - console.log(`libraryPath ${libraryPath} libraryName ${libraryName}`); - - if ( - !mastercopies[libraryName] || - !mastercopies[libraryName][contractVersion] - ) { - throw new Error( - `Could not link ${libraryName} for ${artifact.contractName}` - ); - } - - let { address: libraryAddress } = - mastercopies[libraryName][contractVersion]; - - assert(isAddress(libraryAddress)); - - for (const { length, start: offset } of artifact.linkReferences[ - libraryPath - ][libraryName]) { - assert(length == 20); - - // the offset is in bytes, and does not account for the trailing 0x - const left = 2 + offset * 2; - const right = left + length * 2; - - bytecode = `${bytecode.slice(0, left)}${libraryAddress.slice(2).toLowerCase()}${bytecode.slice(right)}`; - - console.log( - `Replaced library reference at ${offset} with address ${libraryAddress}` - ); - } - } - } - - return bytecode; -} - /** * Resolves the paths to the artifact and build info files for a specified contract. * diff --git a/src/artifact/internal/linkBuildArtifact.ts b/src/artifact/internal/linkBuildArtifact.ts new file mode 100644 index 0000000..f73d8fe --- /dev/null +++ b/src/artifact/internal/linkBuildArtifact.ts @@ -0,0 +1,127 @@ +import assert from "assert"; +import { isAddress } from "ethers"; + +import { BuildArtifact, MastercopyArtifact } from "../../types"; + +/** + * Resolves library links in a build artifact + * + */ +export default function linkBuildArtifact({ + artifact, + contractVersion, + minimalCompilerInput, + mastercopies, +}: { + artifact: BuildArtifact; + contractVersion: string; + minimalCompilerInput?: string; + mastercopies: Record>; +}): BuildArtifact { + const bytecode = linkBytecode(artifact, contractVersion, mastercopies); + const compilerInput = linkCompilerInput( + artifact, + contractVersion, + minimalCompilerInput || artifact.compilerInput, + mastercopies + ); + + return { + ...artifact, + bytecode, + compilerInput, + }; +} + +/** + * Replaces library references in the bytecode with actual deployed addresses. + * + * This function scans the bytecode and replaces placeholder references + * to libraries with their actual on-chain addresses. It ensures that + * the library addresses are valid and properly formatted. + * + * @param {string} bytecode - The bytecode that may contain library references. + * @param {Record} linkReferences - References to libraries, as returned by the compiler. + * @param {Record} libraryAddresses - A map of library names to their deployed addresses. + * @returns {string} - The updated bytecode with library references replaced by actual addresses. + * + * @throws {Error} - Throws if a library address is missing or incorrectly formatted. + */ +function linkBytecode( + artifact: BuildArtifact, + contractVersion: string, + mastercopies: Record> +): string { + let bytecode = artifact.bytecode; + + for (const libraryPath of Object.keys(artifact.linkReferences)) { + for (const libraryName of Object.keys( + artifact.linkReferences[libraryPath] + )) { + console.log(`libraryPath ${libraryPath} libraryName ${libraryName}`); + + if ( + !mastercopies[libraryName] || + !mastercopies[libraryName][contractVersion] + ) { + throw new Error( + `Could not link ${libraryName} for ${artifact.contractName}` + ); + } + + let { address: libraryAddress } = + mastercopies[libraryName][contractVersion]; + + assert(isAddress(libraryAddress)); + + for (const { length, start: offset } of artifact.linkReferences[ + libraryPath + ][libraryName]) { + assert(length == 20); + + // the offset is in bytes, and does not account for the trailing 0x + const left = 2 + offset * 2; + const right = left + length * 2; + + bytecode = `${bytecode.slice(0, left)}${libraryAddress.slice(2).toLowerCase()}${bytecode.slice(right)}`; + + console.log( + `Replaced library reference at ${offset} with address ${libraryAddress}` + ); + } + } + } + + return bytecode; +} + +function linkCompilerInput( + artifact: BuildArtifact, + contractVersion: string, + compilerInput: any, + mastercopies: Record> +): any { + for (const libraryPath of Object.keys(artifact.linkReferences)) { + compilerInput.settings.libraries[libraryPath] = + compilerInput.settings.libraries[libraryPath] || {}; + for (const libraryName of Object.keys( + artifact.linkReferences[libraryPath] + )) { + const libraryAddress = + mastercopies[libraryName]?.[contractVersion]?.address; + if (!libraryAddress) { + continue; + } + + assert(isAddress(libraryAddress)); + + compilerInput.settings = { + ...compilerInput.settings, + libraries: { + ...compilerInput.settings.libraries, + [libraryPath]: { [libraryName]: libraryAddress }, + }, + }; + } + } +} diff --git a/src/artifact/writeMastercopyFromBuild.ts b/src/artifact/writeMastercopyFromBuild.ts index 13d3beb..668da2c 100644 --- a/src/artifact/writeMastercopyFromBuild.ts +++ b/src/artifact/writeMastercopyFromBuild.ts @@ -8,9 +8,8 @@ import { defaultBuildDir, defaultMastercopyArtifactsFile, } from "./internal/paths"; -import getBuildArtifact, { - resolveLinksInBytecode, -} from "./internal/getBuildArtifact"; +import getBuildArtifact from "./internal/getBuildArtifact"; +import linkBuildArtifact from "./internal/linkBuildArtifact"; import { MastercopyArtifact } from "../types"; @@ -60,29 +59,13 @@ export default function writeMastercopyFromBuild({ console.warn(`Warning: overriding artifact for ${contractVersion}`); } - const bytecode = resolveLinksInBytecode( + const artifact = linkBuildArtifact({ + artifact: buildArtifact, contractVersion, - buildArtifact, - mastercopies - ); + minimalCompilerInput, + mastercopies, + }); - const compilerInput = minimalCompilerInput || buildArtifact.compilerInput; - compilerInput.settings = compilerInput.settings || {}; - compilerInput.settings.libraries = compilerInput.settings.libraries || {}; - for (const libraryPath of Object.keys(buildArtifact.linkReferences)) { - compilerInput.settings.libraries[libraryPath] = - compilerInput.settings.libraries[libraryPath] || {}; - for (const libraryName of Object.keys( - buildArtifact.linkReferences[libraryPath] - )) { - const libraryAddress = - mastercopies[libraryName]?.[contractVersion]?.address; - if (libraryAddress) { - compilerInput.settings.libraries[libraryPath][libraryName] = - libraryAddress; - } - } - } const mastercopyArtifact: MastercopyArtifact = { contractName, sourceName: buildArtifact.sourceName, @@ -91,15 +74,15 @@ export default function writeMastercopyFromBuild({ factory, address: predictSingletonAddress({ factory, - bytecode, + bytecode: artifact.bytecode, constructorArgs, salt, }), - bytecode, + bytecode: artifact.bytecode, constructorArgs, salt, abi: buildArtifact.abi, - compilerInput, + compilerInput: artifact.compilerInput, }; const nextMastercopies = { From c1012a30fb915c8fcdd92d863a48ce2235be0edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Fri, 13 Sep 2024 17:08:38 +0200 Subject: [PATCH 4/5] fix: adjust linkCompilerInput --- src/artifact/internal/linkBuildArtifact.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/artifact/internal/linkBuildArtifact.ts b/src/artifact/internal/linkBuildArtifact.ts index f73d8fe..0fe1767 100644 --- a/src/artifact/internal/linkBuildArtifact.ts +++ b/src/artifact/internal/linkBuildArtifact.ts @@ -101,9 +101,8 @@ function linkCompilerInput( compilerInput: any, mastercopies: Record> ): any { + const result = { ...compilerInput }; for (const libraryPath of Object.keys(artifact.linkReferences)) { - compilerInput.settings.libraries[libraryPath] = - compilerInput.settings.libraries[libraryPath] || {}; for (const libraryName of Object.keys( artifact.linkReferences[libraryPath] )) { @@ -115,13 +114,15 @@ function linkCompilerInput( assert(isAddress(libraryAddress)); - compilerInput.settings = { - ...compilerInput.settings, + result.settings = { + ...result.settings, libraries: { - ...compilerInput.settings.libraries, + ...result.settings.libraries, [libraryPath]: { [libraryName]: libraryAddress }, }, }; } } + + return result; } From 7bb75fee1c63f296304447b205ceef32847f07df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Fri, 13 Sep 2024 17:46:34 +0200 Subject: [PATCH 5/5] chore: bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e7fc8da..1b80fc7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gnosis-guild/zodiac-core", - "version": "2.0.3", + "version": "2.0.4", "description": "Zodiac is a composable design philosophy and collection of standards for building DAO ecosystem tooling.", "author": "Auryn Macmillan ", "license": "LGPL-3.0+",