lib- surcify v2 (中文(简体) )
lib -surcify 是 (英语) 强制化用于验证合同的可重用的主干线库。 版本2引入了经过完善抽象的完全重新设计的架构,更好地支持Solity和Vyper合同,更加灵活的验证过程,以及浏览器支持.
概览
lib-sourcify提供了验证,编译和验证智能合同的工具.
库支持使用 Solidity 元数据.json 和 Solidity 和 Vyper 的标准-JSON 输入格式进行校验
安装
npm install @ethereum-sourcify/lib-sourcify
快速启动
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 }
这个例子显示了使用标准JSON输入的固态合同的完整验证流程. 关于Vyper合同或更先进的使用案例,见下文详细章节.
在浏览器中使用
对于浏览器的使用,我们建议使用 网络索尔c 改为 @ethereum-sourcify/compilers。这里是一个如何执行 ISolidityCompiler 接口 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();
建筑
lib-surcify v2由几个关键组件组成:
-
验证:基于一个 Solidity 元数据.json 文件描述合同构建,检查所有源文件是否都存在并有效. 必要时从 IPFS 中获取缺失的来源 .
SolidityMetadataContract: 与元数据和源文件的团结合同processFiles.ts: 用于创建的工具函数SolidityMetadataContract来自文件的实例
-
汇编: 处理合同汇编
AbstractCompilation: 编译的基础类SolidityCompilation: 处理固态汇编VyperCompilation: 处理 Vyper 编译
-
钉死钱: 处理块链交互, 如获取字节代码和交易数据
-
核查: 比较编译的字节代码
Compilation带有一个链上字节代码SourcifyChainVerification: 主持核查进程的主要班级
配置
RPC 超时配置
您可以通过 SourcifyChain 类 :
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 网关配置
您可以配置用于获取缺失源的 IPFS 网关 :
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();
日志配置
您可以设置全局日志级别并提供自定义日志 :
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
},
});
编译器设置
这个 lib-sourcify 库中不包含编译器作为依赖。 相反,你需要提供一个类 执行任何一种 ISolidityCompiler 或者说 IVyperCompiler 界面并传递给需要编译器的任何函数。 我们建议你使用官方 @ethereum-sourcify/compilers 软件包.
在出现错误的情况下 compile 函数, lib-sourcify 期望抛出的错误有公开 errors 包含编译输出的属性 errors 属性.
固态编译器示例
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 编译器示例
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');
钉死钱
Sourcify Chain是一个处理块链相互作用的类,例如取取字节码和交易数据.
它支持 HTTP 头经过醚认证的 RPC.js FetchRequest 对象.
还支持区域方案协调委员会 debug_traceTransaction 财务报告和审定财务报表 trace_call 能够获取工厂合同创建字节代码的方法.
创建“强化事实”
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,
});
使用经认证的RPC
对于需要认证的RPC,您可以在配置中直接指定标题:
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,
});
验证
注:Vyper合同不支持通过元数据文件进行验证,因为它们没有将元数据JSON字段纳入其字节代码. 相反,Vyper合同必须直接使用其源文件和编译器设置进行验证.
用元数据验证团结合同
v2 介绍 SolidityMetadataContract 管理验证工作流程的类 :
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);
对于基于文件的校验 :
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
}
获取缺失的源
每个合同来源都有一个 content 字段中包含作为字符串的固态代码,或从(Github, IPFS, Swarm等)获取源的URL。 如果来源缺失, 您可以获取 :
// Fetch missing sources
await metadataContract.fetchMissing();
将利用配置的森林小组网关获取森林小组资源。 您可以使用 SolidityMetadataContract.setGlobalIpfsGateway() global配置一节中所示的方法.
您可以检查合同是否准备与:
const isCompilable = metadataContract.isCompilable(); // true or false
核查
在v2中,核查过程由 Verification 类 :
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
转换
采用 验证联盟 用于描述从编译的字节代码到链上字节代码的修改.
例如,当不可变变量设定为 0x00..00 在编译后,它们被设定为链字节码中的实际值.
参见 VerA 文档 更多信息.
处理错误
在核查期间,可能发生各种错误。 在 lib- surcify v2 中,与校验相关的错误被抛出为 VerificationError 实例,以扩展 SourcifyLibError 课。 这些错误包括一个消息和一个可以用来处理不同错误案件的错误代码.
错误代码
见 VerificationErrorCode 类型在 验证类型( T) 用于完整错误代码列表.
日志
lib-sourcify 拥有可以在全球配置的基本伐木系统.
您可以使用 setLibSourcifyLoggerLevel(level) 函数,其中:
0是错误1为警告2属于信息5正在调试6这么傻
您可以使用 getLibSourcifyLoggerLevel()。 。 。 .
您可以通过调用来覆盖日志 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为从Etherscan API进口和处理经核实的合同提供公用事业.
从 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
);
根据以太色计算结果创建汇编
// 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();
从v1到v2的迁移指南
Lib-sourcify 第2版带来了图书馆建筑的重大重新设计. 以下是如何从v1迁移到v2:
密钥更改
-
类结构变化数字 :
AbstractCheckedContract被特定语言的汇编类所取代SolidityCheckedContract函数现在被拆分SolidityMetadataContract财务报告和审定财务报表SolidityCompilationVyperCheckedContract现改为:VyperCompilation- 新设
Verification类处理核查进程
-
工作流程变化数字 :
- 审定、汇编和核查现在是单独的步骤
- 对核查进程的更明确的控制
移徙实例
从v1:使用固态检查合同
// V1 code
const checkedContracts = await checkFilesWithMetadata(solc, pathBuffers);
const solidityCheckedContract = checkedContracts[0];
await solidityCheckedContract.fetchMissing();
const match = await verifyDeployed(
solidityCheckedContract,
sourcifyChain,
contractAddress,
);
到 v2: 使用固态元数据合同与验证
// 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;
V1 vs 2 的函数
| v1 函数/ 类 | v2 等价键 |
|---|---|
SolidityCheckedContract | SolidityMetadataContract + 键 SolidityCompilation |
VyperCheckedContract | VyperCompilation |
checkFilesWithMetadata | createMetadataContractsFromFiles |
verifyDeployed | Verification.verify() |
fetchMissing | metadataContract.fetchMissing() |
isValid | metadataContract.isCompilable() |