-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18 from gnosisguild/fix/zodiac-core-library-refer…
…ences-verification Fix missing library references in Zodiac Core mastercopy JSON
- Loading branch information
Showing
5 changed files
with
144 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <[email protected]>", | ||
"license": "LGPL-3.0+", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
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<string, Record<string, MastercopyArtifact>>; | ||
}): 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<string, any>} linkReferences - References to libraries, as returned by the compiler. | ||
* @param {Record<string, string>} 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, Record<string, MastercopyArtifact>> | ||
): 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<string, Record<string, MastercopyArtifact>> | ||
): any { | ||
const result = { ...compilerInput }; | ||
for (const libraryPath of Object.keys(artifact.linkReferences)) { | ||
for (const libraryName of Object.keys( | ||
artifact.linkReferences[libraryPath] | ||
)) { | ||
const libraryAddress = | ||
mastercopies[libraryName]?.[contractVersion]?.address; | ||
if (!libraryAddress) { | ||
continue; | ||
} | ||
|
||
assert(isAddress(libraryAddress)); | ||
|
||
result.settings = { | ||
...result.settings, | ||
libraries: { | ||
...result.settings.libraries, | ||
[libraryPath]: { [libraryName]: libraryAddress }, | ||
}, | ||
}; | ||
} | ||
} | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters