@ethereum-sourcify/lib-sourcify

中文文档
3.8.0发布于 2026/11/03MITTypeScriptESM + CJS近 30 天下载 4.1万

Library for Sourcify's contract verification methods, contract validation, types, and interfaces.

原始使用文档
文档目录30 节
  1. Overview
  2. Installation
  3. Quick Start
  4. Using in browser
  5. Architecture
  6. Configuration
  7. RPC Timeout Configuration
  8. IPFS Gateway Configuration
  9. Logging Configuration
  10. Compiler Setup
  11. Solidity Compiler Example
  12. Vyper Compiler Example
  13. SourcifyChain
  14. Creating a SourcifyChain Instance
  15. Using Authenticated RPCs
  16. Validation
  17. Validating Solidity Contracts with Metadata
  18. Fetching Missing Sources
  19. Verification
  20. Transformations
  21. Error Handling
  22. Error Codes
  23. Logging
  24. EtherscanUtils
  25. Fetching Contract Data from Etherscan
  26. Creating Compilations from Etherscan Results
  27. Migration Guide from v1 to v2
  28. Key Changes
  29. Migration Examples
  30. Functions of v1 vs v2

lib-sourcify v2

codecov

lib-sourcify is Sourcify's reusable backbone library for verifying contracts. Version 2 introduces a completely redesigned architecture with improved abstractions, better support for both Solidity and Vyper contracts, a more flexible verification process, and browser support.

Overview

lib-sourcify provides tools to validate, compile, and verify smart contracts.

The library supports verification with Solidity metadata.json and with both Solidity and Vyper's standard-JSON input formats

Installation

npm install @ethereum-sourcify/lib-sourcify

Quick Start

import {
  SolidityCompilation,
  Verification,
  SourcifyChain,
  ISolidityCompiler,
  SolidityJsonInput,
  SolidityOutput,
} from '@ethereum-sourcify/lib-sourcify';
import { useSolidityCompiler } from '@ethereum-sourcify/compilers';
import * as fs from 'fs';

// Step 1: Setup your compiler
class Solc implements ISolidityCompiler {
  private solcRepoPath: string;
  private solJsonRepoPath: string;

  constructor(solcRepoPath: string, solJsonRepoPath: string) {
    this.solcRepoPath = solcRepoPath;
    this.solJsonRepoPath = solJsonRepoPath;
  }

  async compile(
    version: string,
    solcJsonInput: SolidityJsonInput,
    forceEmscripten: boolean = false,
  ): Promise<SolidityOutput> {
    return await useSolidityCompiler(
      this.solcRepoPath, // useSolidityCompiler will automatically download and store solc here
      this.solJsonRepoPath, // useSolidityCompiler will automatically download and store solcjs here
      version,
      solcJsonInput,
      forceEmscripten,
    );
  }
}

const solc = new Solc('/path/to/solc', '/path/to/solcjs');

// Step 2: Prepare your standard JSON input
const jsonInput = {
  language: 'Solidity',
  sources: {
    'Contract.sol': {
      content: 'contract MyContract { function foo() public {} }',
    },
  },
  settings: {
    optimizer: {
      enabled: true,
      runs: 200,
    },
    outputSelection: {
      '*': [],
    },
  },
} as SolidityJsonInput;

// Step 3: Create a compilation
const compilation = new SolidityCompilation(
  solc,
  '0.8.20', // compiler version
  jsonInput,
  {
    path: 'Contract.sol',
    name: 'MyContract', // The name of your contract
  },
);

// Step 4: Set up a SourcifyChain instance
const myChain = new SourcifyChain({
  name: 'My EVM Chain',
  chainId: 1337,
  rpc: ['http://localhost:8545'],
  supported: true,
});

// Step 5: Verify the contract
const verification = new Verification(
  compilation,
  myChain,
  '0xc0ffee254729296a45a3885639AC7E10F9d54979',
);

await verification.verify();

// Step 6: Check verification status
console.log(verification.status); // { runtimeMatch: 'perfect', creationMatch: null }

This example shows the complete verification flow for a Solidity contract using standard JSON input. For Vyper contracts or more advanced use cases, see the detailed sections below.

Using in browser

For browser usage, we recommend using web-solc instead of @ethereum-sourcify/compilers. Here's an example of how to implement the ISolidityCompiler interface with web-solc:

import {
  ISolidityCompiler,
  SolidityJsonInput,
} from '@ethereum-sourcify/lib-sourcify';
import { fetchSolc } from 'web-solc';

class Solc implements ISolidityCompiler {
  async compile(
    version: string,
    solcJsonInput: SolidityJsonInput,
  ): Promise<any> {
    const { compile } = await fetchSolc(version);
    return await compile(solcJsonInput);
  }
}

const solc = new Solc();

Architecture

lib-sourcify v2 consists of several key components:

  • Validation: Based on a Solidity metadata.json file that describes a contract build, checks if all source files are present and valid. Fetches missing sources from IPFS if necessary.

    • SolidityMetadataContract: Represents a Solidity contract with its metadata and source files
    • processFiles.ts: Utility functions for creating SolidityMetadataContract instances from files
  • Compilation: Handles contract compilation

    • AbstractCompilation: Base class for compilation
    • SolidityCompilation: Handles Solidity compilation
    • VyperCompilation: Handles Vyper compilation
  • SourcifyChain: Handles blockchain interactions such as fetching bytecode and transaction data

  • Verification: Compares compiled bytecode from a Compilation with an on-chain bytecode from a SourcifyChain

    • Verification: Main class orchestrating the verification process

Configuration

RPC Timeout Configuration

You can set a global timeout for all RPC requests through the SourcifyChain class:

import { SourcifyChain } from '@ethereum-sourcify/lib-sourcify';

// Set global RPC timeout to 30 seconds
SourcifyChain.setGlobalRpcTimeout(30 * 1000);

// Get the current global RPC timeout
const timeout = SourcifyChain.getGlobalRpcTimeout(); // Default is 10 seconds

IPFS Gateway Configuration

You can configure the IPFS gateway used for fetching missing sources:

import { SolidityMetadataContract } from '@ethereum-sourcify/lib-sourcify';

// Set a custom IPFS gateway
SolidityMetadataContract.setGlobalIpfsGateway({
  url: 'https://my-ipfs-gateway.com/ipfs/',
  headers: { Authorization: 'Bearer my-token' },
});

// Get the current IPFS gateway configuration
const gateway = SolidityMetadataContract.getGlobalIpfsGateway();

Logging Configuration

You can set the global log level and provide a custom logger:

import {
  setLibSourcifyLoggerLevel,
  setLibSourcifyLogger,
  getLibSourcifyLoggerLevel,
} from '@ethereum-sourcify/lib-sourcify';

// Set the log level
setLibSourcifyLoggerLevel(5); // 0=errors, 1=warnings, 2=info, 5=debug, 6=silly

// Get the current log level
const logLevel = getLibSourcifyLoggerLevel();

// Use a custom logger
setLibSourcifyLogger({
  logLevel: 2,
  setLevel(level: number) {
    this.logLevel = level;
  },
  log(level, msg) {
    // Custom logging implementation
  },
});

Compiler Setup

The lib-sourcify library does not come with compilers as dependencies. Instead, you need to provide a class that implements either the ISolidityCompiler or IVyperCompiler interface and pass it to any function that requires a compiler. We suggest you to use the official @ethereum-sourcify/compilers package.

In the case of an error in the compile function, lib-sourcify expects the thrown error to have a public errors property containing the compilation output's errors property.

Solidity Compiler Example

import {
  SolidityOutput,
  ISolidityCompiler,
  SolidityJsonInput,
} from '@ethereum-sourcify/lib-sourcify';
import { useSolidityCompiler } from '@ethereum-sourcify/compilers';

class Solc implements ISolidityCompiler {
  constructor(
    private solcRepoPath: string,
    private solJsonRepoPath: string,
  ) {}

  async compile(
    version: string,
    solcJsonInput: SolidityJsonInput,
    forceEmscripten: boolean = false,
  ): Promise<SolidityOutput> {
    return await useSolidityCompiler(
      this.solcRepoPath,
      this.solJsonRepoPath,
      version,
      solcJsonInput,
      forceEmscripten,
    );
  }
}

const solc = new Solc('/path/to/solc/repo', '/path/to/solcjs/repo');

Vyper Compiler Example

import { useVyperCompiler } from '@ethereum-sourcify/compilers';

import {
  IVyperCompiler,
  VyperOutput,
  VyperJsonInput,
} from '@ethereum-sourcify/lib-sourcify';

class Vyper implements IVyperCompiler {
  constructor(private vyperRepoPath: string) {}

  async compile(
    version: string,
    vyperJsonInput: VyperJsonInput,
  ): Promise<VyperOutput> {
    return await useVyperCompiler(this.vyperRepoPath, version, vyperJsonInput);
  }
}
const vyper = new Vyper('/path/to/vyper/repo');

SourcifyChain

SourcifyChain is a class that handles blockchain interactions such as fetching bytecode and transaction data.

It supports HTTP header authenticated RPCs through ethers.js FetchRequest objects.

Also supports RPCs with debug_traceTransaction and trace_call methods to be able to fetch creation bytecode for factory contracts.

Creating a SourcifyChain Instance

import { SourcifyChain } from '@ethereum-sourcify/lib-sourcify';
import { FetchRequest } from 'ethers';

// Create a SourcifyChain for Ethereum Mainnet
const mainnetChain = new SourcifyChain({
  name: 'Ethereum Mainnet',
  chainId: 1,
  rpc: [
    'https://eth.llamarpc.com',
    new FetchRequest({
      url: 'https://authenticated-rpc.com',
      headers: {
        Authorization: 'Bearer ...',
      },
    }),
    'https://eth-mainnet.g.alchemy.com/v2/MY_API_KEY',
  ],
  traceSupportedRPCs: [
    {
      type: 'trace_transaction', // or 'debug_traceTransaction'
      index: 2, // index of the RPC in the rpc array
    },
  ],
  supported: true,
});

Using Authenticated RPCs

For RPCs that require authentication, you can specify the headers directly in the configuration:

import { SourcifyChain } from '@ethereum-sourcify/lib-sourcify';

const authenticatedChain = new SourcifyChain({
  name: 'Protected Network',
  chainId: 1234,
  rpc: [
    {
      type: 'FetchRequest',
      url: 'https://protected-rpc.example.com',
      headers: [
        {
          headerName: 'Authorization',
          headerValue: 'Bearer my-auth-token',
        },
        {
          headerName: 'X-API-Key',
          headerValue: 'my-api-key',
        },
      ],
    },
  ],
  supported: true,
});

Validation

Note: Vyper contracts do not support validation through metadata files since they do not include a metadata JSON field in their bytecode. Instead, Vyper contracts must be verified directly using their source files and compiler settings.

Validating Solidity Contracts with Metadata

v2 introduces the SolidityMetadataContract class which manages the validation workflow:

import { SolidityMetadataContract } from '@ethereum-sourcify/lib-sourcify';

// Create a SolidityMetadataContract with metadata and sources
const metadataContract = new SolidityMetadataContract(metadata, sources);

// Create a compilation object that can be used for verification
const compilation = await metadataContract.createCompilation(solidityCompiler);

For file-based validation:

import {
  createMetadataContractsFromFiles,
  PathBuffer,
} from '@ethereum-sourcify/lib-sourcify';

const pathBuffers: PathBuffer[] = [];
pathBuffers.push({
  path: filePath,
  buffer: fs.readFileSync(filePath),
});

// Create SolidityMetadataContract objects from files
const metadataContracts = await createMetadataContractsFromFiles(pathBuffers);

// Create compilation objects
for (const contract of metadataContracts) {
  const compilation = await contract.createCompilation(solidityCompiler);
  // Use compilation for verification
}

Fetching Missing Sources

Each contract source either has a content field containing the Solidity code as a string, or URLs to fetch the sources from (Github, IPFS, Swarm etc.). If sources are missing, you can fetch them:

// Fetch missing sources
await metadataContract.fetchMissing();

IPFS resources will be fetched using the configured IPFS gateway. You can configure the gateway using the SolidityMetadataContract.setGlobalIpfsGateway() method as shown in the Global Configuration section.

You can check if a contract is ready to be compiled with:

const isCompilable = metadataContract.isCompilable(); // true or false

Verification

In v2, the verification process is handled by the Verification class:

import { Verification, SourcifyChain } from '@ethereum-sourcify/lib-sourcify';

// Set up the SourcifyChain
const chain = new SourcifyChain({
  name: 'Ethereum Mainnet',
  chainId: 1,
  rpc: ['https://eth.llamarpc.com'],
  supported: true,
});

// Create a verification instance
const verification = new Verification(
  compilation,
  chain,
  contractAddress,
  creatorTxHash, // optional, for creation bytecode verification
);

// Perform verification
await verification.verify();

// Check verification status
console.log(verification.status.runtimeMatch); // 'perfect', 'partial', or null

Transformations

Sourcify adopts the Verifier Alliance format called "transformations" to describe the changes from the compiled bytecode to onchain bytecode for a verification.

E.g. while immutable variables are set to 0x00..00 after compilation, they are set to the actual value in the onchain bytecode.

Refer to VerA Docs for more information.

Error Handling

During verification, various errors can occur. In lib-sourcify v2, errors related to verification are thrown as VerificationError instances, which extend the SourcifyLibError class. These errors include a message and an error code that can be used to handle different error cases.

Error Codes

See VerificationErrorCode type in VerificationTypes.ts for the full list of error codes.

Logging

lib-sourcify has a basic logging system that can be configured globally.

You can specify the log level using the setLibSourcifyLoggerLevel(level) function where:

  • 0 is errors
  • 1 is warnings
  • 2 is infos
  • 5 is debug
  • 6 is silly

You can get the current log level using getLibSourcifyLoggerLevel().

You can override the logger by calling setLogger(logger: ILibSourcifyLogger):

const winston = require('winston');
const myCustomLogger = winston.createLogger({
  // ...
});

setLibSourcifyLogger({
  logLevel: 2, // What levels to log. E.g. Log anything lower than info: error and warning
  setLevel(level: number) {
    this.logLevel = level;
  },
  log(level, msg) {
    if (level <= this.logLevel) {
      switch (level) {
        case 0:
          myCustomLogger.error(msg);
          break;
        case 1:
          myCustomLogger.warn(msg);
          break;
        case 2:
          myCustomLogger.info(msg);
          break;
        case 5:
          myCustomLogger.debug(msg);
          break;
      }
    }
  },
});

EtherscanUtils

EtherscanUtils provides utilities for importing and processing verified contracts from Etherscan APIs.

Fetching Contract Data from Etherscan

import { EtherscanUtils } from '@ethereum-sourcify/lib-sourcify';

// Fetch contract source code and metadata from Etherscan
const etherscanResult = await EtherscanUtils.fetchFromEtherscan(
  1, // chainId
  '0x6B175474E89094C44Da98b954EedeAC495271d0F', // contract address
  'YOUR_API_KEY', // API key
);

Creating Compilations from Etherscan Results

// Create a compilation object directly from Etherscan data
const compilation = await EtherscanUtils.getCompilationFromEtherscanResult(
  etherscanResult,
  solidityCompiler, // ISolidityCompiler instance
  vyperCompiler, // IVyperCompiler instance (for Vyper contracts)
);

// Use the compilation for verification
const verification = new Verification(compilation, chain, contractAddress);
await verification.verify();

Migration Guide from v1 to v2

Version 2 of lib-sourcify brings a significant redesign of the library's architecture. Here's how to migrate from v1 to v2:

Key Changes

  1. Class Structure Changes:

    • AbstractCheckedContract is replaced by language-specific compilation classes
    • SolidityCheckedContract functionality is now split between SolidityMetadataContract and SolidityCompilation
    • VyperCheckedContract is now represented by VyperCompilation
    • New Verification class handles the verification process
  2. Workflow Changes:

    • Validation, compilation, and verification are now separate steps
    • More explicit control over the verification process

Migration Examples

From v1: Using SolidityCheckedContract

// V1 code
const checkedContracts = await checkFilesWithMetadata(solc, pathBuffers);
const solidityCheckedContract = checkedContracts[0];
await solidityCheckedContract.fetchMissing();
const match = await verifyDeployed(
  solidityCheckedContract,
  sourcifyChain,
  contractAddress,
);

To v2: Using SolidityMetadataContract and Verification

// V2 code
import {
  createMetadataContractsFromFiles,
  Verification,
} from '@ethereum-sourcify/lib-sourcify';

// Create metadata contracts from files
const metadataContracts = await createMetadataContractsFromFiles(pathBuffers);
const metadataContract = metadataContracts[0];

// Fetch missing sources
await metadataContract.fetchMissing();

// Create compilation
const compilation = await metadataContract.createCompilation(solc);

// Create verification instance
const verification = new Verification(
  compilation,
  sourcifyChain,
  contractAddress,
);

// Perform verification
await verification.verify();

// Check verification status
const status = verification.status;

Functions of v1 vs v2

v1 Function/Classv2 Equivalent
SolidityCheckedContractSolidityMetadataContract + SolidityCompilation
VyperCheckedContractVyperCompilation
checkFilesWithMetadatacreateMetadataContractsFromFiles
verifyDeployedVerification.verify()
fetchMissingmetadataContract.fetchMissing()
isValidmetadataContract.isCompilable()

版本与发布记录

@ethereum-sourcify/lib-sourcify 共发布 67 个版本,首次发布于 2023/03/13;过去 12 个月发布了 19 个版本。

版本发布日期距今
3.8.0latest2026/11/0310 天前
3.7.42026/10/2123 天前
3.7.32026/10/051 个月前
3.7.22026/09/221 个月前
3.7.12026/09/012 个月前
3.7.02026/08/202 个月前

关于 @ethereum-sourcify/lib-sourcify 的常见问题

@ethereum-sourcify/lib-sourcify 是什么?

Library for Sourcify's contract verification methods, contract validation, types, and interfaces.

如何安装 @ethereum-sourcify/lib-sourcify?

在项目目录运行 npm install @ethereum-sourcify/lib-sourcify,或使用 pnpm add / yarn add / bun add。

@ethereum-sourcify/lib-sourcify 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@ethereum-sourcify/lib-sourcify 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@ethereum-sourcify/lib-sourcify 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js v26.10.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@ethereum-sourcify/lib-sourcify 可以商用吗?

@ethereum-sourcify/lib-sourcify 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@ethereum-sourcify/lib-sourcify 的下载量有多少?

根据 npm 官方下载统计,@ethereum-sourcify/lib-sourcify 在 2026/10/14 – 2026/11/12 这 30 天内被下载 40,590 次,日均约 1,353 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@ethereum-sourcify/lib-sourcify 还在维护吗?

最新版本 3.8.0 发布于 2026/11/03(10 天前);至今共发布 67 个版本,其中过去 12 个月发布了 19 个;首次发布于 2023/03/13。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。