Skip to content

Commit 2714dad

Browse files
authored
Pre 0.4.11 cbor auxdata (#2277)
Fixes #2217 It wasn't possible to verify contracts that have a cborAuxdata and solc <=0.4.11 because the `.auxdata` field in legacyAssembly was just introduced on 0.4.12. This handles the cases when the compiler is <=0.4.11 and also <0.4.7 when metadata was first introduced. Also handles when contractIdentifier path was missing before solc 0.4.9 and when there was no metadata 09692c0 Adds tests for the cases
2 parents d11e396 + 8e8e7fa commit 2714dad

File tree

21 files changed

+519
-42
lines changed

21 files changed

+519
-42
lines changed

package-lock.json

Lines changed: 22 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/compilers-types/src/CompilationTypes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Abi } from "abitype";
1+
import { JsonFragment } from "ethers";
22
import { SolidityOutputError, SoliditySettings } from "./SolidityTypes";
33
import { VyperOutputError } from "./VyperTypes";
44

@@ -75,7 +75,7 @@ export interface Userdoc {
7575
export type OutputError = SolidityOutputError | VyperOutputError;
7676

7777
export interface MetadataOutput {
78-
abi: Abi;
78+
abi: JsonFragment[];
7979
devdoc?: Devdoc;
8080
userdoc?: Userdoc;
8181
}

packages/compilers-types/src/SolidityTypes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Abi } from "abitype";
1+
import { JsonFragment } from "ethers";
22
import { Devdoc, Userdoc, LinkReferences } from "./CompilationTypes";
33

44
interface File {
@@ -158,7 +158,7 @@ export interface StorageLayout {
158158
};
159159
}
160160
export interface SolidityOutputContract {
161-
abi: Abi;
161+
abi: JsonFragment[];
162162
metadata: string;
163163
userdoc?: Userdoc;
164164
devdoc?: Devdoc;

packages/compilers-types/src/VyperTypes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Abi } from "abitype";
1+
import { JsonFragment } from "ethers";
22
import { Devdoc } from "./CompilationTypes";
33
import { Userdoc } from "./CompilationTypes";
44

@@ -63,7 +63,7 @@ export interface VyperOutputSources {
6363
}
6464

6565
export interface VyperOutputContract {
66-
abi: Abi;
66+
abi: JsonFragment[];
6767
userdoc: Userdoc;
6868
devdoc: Devdoc;
6969
ir: string;

packages/lib-sourcify/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,9 @@
4141
"@ethereumjs/statemanager": "2.4.0",
4242
"@ethereumjs/util": "9.1.0",
4343
"@ethereumjs/vm": "8.1.1",
44-
"@ethersproject/abi": "5.8.0",
4544
"@ethersproject/bignumber": "5.8.0",
4645
"@ethersproject/bytes": "5.8.0",
4746
"@fairdatasociety/bmt-js": "2.1.0",
48-
"abitype": "1.0.8",
4947
"bs58": "5.0.0",
5048
"ethers": "6.15.0",
5149
"jszip": "3.10.1",

packages/lib-sourcify/src/Compilation/CompilationTypes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export type CompilationLanguage = 'Solidity' | 'Vyper';
3535
export type CompilationErrorCode =
3636
| 'cannot_generate_cbor_auxdata_positions'
3737
| 'invalid_compiler_version'
38+
| 'unsupported_compiler_version'
3839
| 'contract_not_found_in_compiler_output'
3940
| 'compiler_error'
4041
| 'no_compiler_output'

packages/lib-sourcify/src/Compilation/SolidityCompilation.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { AuxdataStyle, splitAuxdata } from '@ethereum-sourcify/bytecode-utils';
2+
import semver from 'semver';
23
import { AbstractCompilation } from './AbstractCompilation';
34
import {
45
ImmutableReferences,
@@ -41,6 +42,14 @@ export class SolidityCompilation extends AbstractCompilation {
4142
public compilationTarget: CompilationTarget,
4243
) {
4344
super(compilerVersion, jsonInput);
45+
46+
// Throw error for unsupported compiler versions
47+
if (semver.lt(this.compilerVersion, '0.4.11')) {
48+
throw new CompilationError({
49+
code: 'unsupported_compiler_version',
50+
});
51+
}
52+
4453
this.initSolidityJsonInput();
4554
}
4655

@@ -96,6 +105,65 @@ export class SolidityCompilation extends AbstractCompilation {
96105
*/
97106
public async generateCborAuxdataPositions(forceEmscripten = false) {
98107
try {
108+
// Handle legacy Solidity versions with different auxdata support
109+
// CBOR auxdata was introduced in Solidity 0.4.7 https://github.com/ethereum/solidity/releases/tag/v0.4.7
110+
if (semver.lt(this.compilerVersion, '0.4.7')) {
111+
// No auxdata exists in versions before 0.4.7
112+
this._creationBytecodeCborAuxdata = {};
113+
this._runtimeBytecodeCborAuxdata = {};
114+
return;
115+
}
116+
117+
// For versions 0.4.7-0.4.11, auxdata exists but is not in legacyAssembly https://github.com/ethereum/sourcify/issues/2217
118+
if (semver.lte(this.compilerVersion, '0.4.11')) {
119+
// Extract auxdata directly from the end of bytecodes using splitAuxdata
120+
// Runtime bytecode auxdata
121+
const [, runtimeAuxdataCbor, runtimeCborLengthHex] = splitAuxdata(
122+
this.runtimeBytecode,
123+
this.auxdataStyle,
124+
);
125+
126+
if (runtimeAuxdataCbor) {
127+
const auxdataFromRawRuntimeBytecode = `${runtimeAuxdataCbor}${runtimeCborLengthHex}`;
128+
this._runtimeBytecodeCborAuxdata = {
129+
'1': {
130+
offset:
131+
this.runtimeBytecode.substring(2).length / 2 -
132+
parseInt(runtimeCborLengthHex, 16) -
133+
2, // bytecode has 2 bytes of cbor length prefix at the end
134+
value: `0x${auxdataFromRawRuntimeBytecode}`,
135+
},
136+
};
137+
} else {
138+
this._runtimeBytecodeCborAuxdata = {};
139+
}
140+
141+
// Creation bytecode auxdata
142+
// We'll try to extract the auxdata from the end of the bytecode
143+
// If it's not at the end and somewhere else, there isn't much we can do. The verification will likely fail.
144+
const [, creationAuxdataCbor, creationCborLengthHex] = splitAuxdata(
145+
this.creationBytecode,
146+
this.auxdataStyle,
147+
);
148+
149+
if (creationAuxdataCbor) {
150+
const auxdataFromRawCreationBytecode = `${creationAuxdataCbor}${creationCborLengthHex}`;
151+
this._creationBytecodeCborAuxdata = {
152+
'1': {
153+
offset:
154+
this.creationBytecode.substring(2).length / 2 -
155+
parseInt(creationCborLengthHex, 16) -
156+
2, // bytecode has 2 bytes of cbor length prefix at the end
157+
value: `0x${auxdataFromRawCreationBytecode}`,
158+
},
159+
};
160+
} else {
161+
this._creationBytecodeCborAuxdata = {};
162+
}
163+
return;
164+
}
165+
166+
// For versions > 0.4.11, use the existing legacyAssembly-based approach
99167
// Auxdata array extracted from the compiler's `legacyAssembly` field
100168
const auxdatasFromCompilerOutput = findAuxdatasInLegacyAssembly(
101169
(this.contractCompilerOutput as SolidityOutputContract).evm

packages/lib-sourcify/src/Verification/Transformations.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import {
88
CompiledContractCborAuxdata,
99
StringMap,
1010
} from '../Compilation/CompilationTypes';
11-
import { AbiConstructor } from 'abitype';
12-
import { defaultAbiCoder as abiCoder, ParamType } from '@ethersproject/abi';
13-
import { id as keccak256Str } from 'ethers';
11+
import { AbiCoder, id as keccak256Str, Interface } from 'ethers';
1412
import { logError } from '../logger';
1513

14+
const abiCoder = AbiCoder.defaultAbiCoder();
15+
1616
export type Transformation = {
1717
type: 'insert' | 'replace';
1818
reason:
@@ -202,11 +202,8 @@ export function extractConstructorArgumentsTransformation(
202202
populatedRecompiledBytecode,
203203
onchainCreationBytecode,
204204
);
205-
const constructorAbiParamInputs = (
206-
metadata?.output?.abi?.find(
207-
(param) => param.type === 'constructor',
208-
) as AbiConstructor
209-
)?.inputs as ParamType[];
205+
const constructorAbiParamInputs = new Interface(metadata?.output?.abi).deploy
206+
.inputs;
210207
if (abiEncodedConstructorArguments) {
211208
if (!constructorAbiParamInputs) {
212209
throw new Error(

packages/lib-sourcify/src/Verification/VerificationTypes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Abi } from 'abitype';
1+
import { JsonFragment } from 'ethers';
22
import {
33
CompilationLanguage,
44
CompilationTarget,
@@ -109,7 +109,7 @@ export interface VerificationExport {
109109
>;
110110
};
111111
contractCompilerOutput: {
112-
abi?: Abi;
112+
abi?: JsonFragment[];
113113
userdoc?: Userdoc;
114114
devdoc?: Devdoc;
115115
storageLayout?: StorageLayout;

0 commit comments

Comments
 (0)