diff --git a/src/deployer/Linker.ts b/src/deployer/Linker.ts index 1ef01d2..b24b25d 100644 --- a/src/deployer/Linker.ts +++ b/src/deployer/Linker.ts @@ -44,6 +44,8 @@ export class Linker { }); } + linksToApply = this._fillLinksToApply(bytecode, artifact, neededLibraries); + if (linksToApply.size < neededLibraries.length) { const separatelyDeployedLibraries = await this._findMissingLibraries( neededLibraries.filter((lib) => !linksToApply.has(`${lib.sourceName}:${lib.libName}`)), @@ -143,10 +145,55 @@ export class Linker { } } + private static _fillLinksToApply( + bytecode: string, + artifact: Artifact, + libraries: NeededLibrary[], + ): Map { + const linksToApplyFilled: Map = new Map(); + + for (const { sourceName, libName } of libraries) { + const linkReferences = artifact.linkReferences[sourceName][libName]; + + for (const { start, length } of linkReferences) { + const [isLinkedLibrary, address] = this._getLinkedLibrary(bytecode, start, length); + + if (isLinkedLibrary) { + linksToApplyFilled.set(`${sourceName}:${libName}`, { + sourceName: sourceName, + libraryName: libName, + address, + }); + } + } + } + + return linksToApplyFilled; + } + + private static _getLinkedLibrary(bytecode: string, start: number, length: number): [boolean, string] { + const prefixLength = start * 2; + const prefix = bytecode.slice(prefixLength + 2, prefixLength + 5); + + const suffixStart = (start + length) * 2; + const suffix = bytecode.slice(suffixStart - 1, suffixStart + 2); + + const address = bytecode.slice(prefixLength + 2, suffixStart + 2); + + return [`${prefix}${suffix}` !== "__$$__", `0x${address}`]; + } + private static _linkBytecode(bytecode: string, artifact: Artifact, libraries: Link[]): string { for (const { sourceName, libraryName, address } of libraries) { const linkReferences = artifact.linkReferences[sourceName][libraryName]; + for (const { start, length } of linkReferences) { + const [isLinkedLibrary] = this._getLinkedLibrary(bytecode, start, length); + + if (isLinkedLibrary) { + continue; + } + const prefixLength = 2 + start * 2; const prefix = bytecode.slice(0, prefixLength); diff --git a/src/deployer/adapters/TruffleAdapter.ts b/src/deployer/adapters/TruffleAdapter.ts index bd73ea9..2c80401 100644 --- a/src/deployer/adapters/TruffleAdapter.ts +++ b/src/deployer/adapters/TruffleAdapter.ts @@ -69,7 +69,11 @@ export class TruffleAdapter extends Adapter { } public getRawBytecode(instance: TruffleContract): string { - return bytecodeToString(instance.bytecode); + try { + return bytecodeToString(instance.binary); + } catch { + return bytecodeToString(instance.bytecode); + } } public getContractName(instance: Instance, parameters: OverridesAndName): string { @@ -80,8 +84,8 @@ export class TruffleAdapter extends Adapter { try { return ArtifactProcessor.tryGetContractName(this.getRawBytecode(instance)); } catch { - if ((instance as any).contractName) { - return (instance as any).contractName; + if ((instance as any)._hArtifact) { + return this._getFullyQualifiedName(instance as any) || (instance as any).contractName; } return UNKNOWN_CONTRACT_NAME; @@ -238,4 +242,12 @@ export class TruffleAdapter extends Adapter { return UNKNOWN_TRANSACTION_NAME; } + + private _getFullyQualifiedName(instance: any): string | undefined { + if (!instance._hArtifact.sourceName || !instance._hArtifact.contractName) { + return undefined; + } + + return `${instance._hArtifact.sourceName}:${instance._hArtifact.contractName}`; + } }