Rust智能合约编译器工具foundry-compilers-artifacts的使用,高效解析与生成Solidity和Vyper合约编译产物
Rust智能合约编译器工具foundry-compilers-artifacts的使用,高效解析与生成Solidity和Vyper合约编译产物
安装
在项目目录中运行以下Cargo命令:
cargo add foundry-compilers-artifacts
或者在Cargo.toml中添加以下行:
foundry-compilers-artifacts = "0.18.2"
基本使用示例
以下是一个使用foundry-compilers-artifacts解析和生成Solidity合约编译产物的完整示例:
use foundry_compilers_artifacts::{Artifact, SolcArtifact};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 读取已编译的Solidity合约JSON文件
let artifact_json = r#"
{
"abi": [/* ABI定义 */],
"bytecode": "0x...",
"deployedBytecode": "0x...",
"metadata": { /* 元数据 */ }
}"#;
// 解析JSON为Artifact
let artifact: Artifact = serde_json::from_str(artifact_json)?;
// 访问合约信息
if let Some(contract) = artifact.contracts.values().next() {
println!("合约ABI: {:?}", contract.abi);
println!("字节码: {}", contract.evm.bytecode.object);
println!("部署字节码: {}", contract.evm.deployed_bytecode.object);
}
Ok(())
}
处理Vyper合约示例
以下示例展示如何处理Vyper合约的编译产物:
use foundry_compilers_artifacts::{VyperArtifact, Artifact};
fn process_vyper_artifact() -> Result<(), Box<dyn std::error::Error>> {
// 读取Vyper合约编译产物
let vyper_json = r#"
{
"abi": [/* ABI定义 */],
"bytecode": "0x...",
"bytecode_runtime": "0x...",
"compiler_version": "0.3.7"
}"#;
// 解析为VyperArtifact
let artifact: VyperArtifact = serde_json::from_str(vyper_json)?;
println!("Vyper合约详细信息:");
println!("编译器版本: {}", artifact.compiler_version);
println!("ABI: {:?}", artifact.abi);
println!("字节码: {}", artifact.bytecode);
println!("运行时字节码: {}", artifact.bytecode_runtime);
Ok(())
}
高级用法:生成编译产物
use foundry_compilers_artifacts::{Contract, Bytecode, DeployedBytecode};
fn generate_artifact() -> Result<(), Box<dyn std::error::Error>> {
// 创建一个新的合约编译产物
let contract = Contract {
abi: Some(vec![/* ABI条目 */]),
evm: Bytecode {
bytecode: Some(BytecodeObject {
object: "0x6060...".to_string(),
// 其他字段...
}),
deployed_bytecode: DeployedBytecode {
bytecode: Some(BytecodeObject {
object: "0x6060...".to_string(),
// 其他字段...
}),
// 其他字段...
},
// 其他字段...
},
// 其他字段...
};
// 序列化为JSON
let json = serde_json::to_string_pretty(&contract)?;
println!("生成的合约JSON:\n{}", json);
Ok(())
}
完整示例demo
以下是一个结合所有功能的完整示例:
use foundry_compilers_artifacts::{
Artifact, SolcArtifact, VyperArtifact,
Contract, Bytecode, DeployedBytecode, BytecodeObject
};
use serde_json;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 解析Solidity合约
let sol_artifact_json = r#"
{
"contracts": {
"MyContract.sol": {
"MyContract": {
"abi": [{"inputs":[],"name":"getValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],
"evm": {
"bytecode": {
"object": "0x6080604052348015600f57600080fd5b506004361060285760003560e01c80632096525514602d575b600080fd5b60336047565b604051603e9190605b565b60405180910390f35b60005481565b6055816074565b82525050565b6000602082019050606e6000830184604e565b92915050565b600081905091905056fea2646970667358221220b5d4a1c4f8f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e64736f6c63430008110033"
},
"deployedBytecode": {
"object": "0x6080604052348015600f57600080fd5b506004361060285760003560e01c80632096525514602d575b600080fd5b60336047565b604051603e9190605b565b60405180910390f35b60005481565b6055816074565b82525050565b6000602082019050606e6000830184604e565b92915050565b600081905091905056fea2646970667358221220b5d4a1c4f8f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e64736f6c63430008110033"
}
}
}
}
}
}"#;
let sol_artifact: Artifact = serde_json::from_str(sol_artifact_json)?;
println!("=== Solidity合约 ===");
if let Some(contract) = sol_artifact.contracts.values().next() {
if let Some(c) = contract.values().next() {
println!("ABI: {:?}", c.abi);
println!("字节码: {}", c.evm.bytecode.object);
}
}
// 2. 解析Vyper合约
let vyper_json = r#"
{
"abi": [{"name": "foo", "inputs": [], "outputs": [{"type": "uint256"}], "stateMutability": "view", "type": "function"}],
"bytecode": "0x6060604052341561000c57fe5b5b6000805460010190555b5b6097806100256000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c298557814603d575bfe5b3415604457fe5b605560048080359060200190919050506057565b005b80600054016000819055505b505600a165627a7a7230582010b5d4a1c4f8f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e0029",
"bytecode_runtime": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c298557814603d575bfe5b3415604457fe5b605560048080359060200190919050506057565b005b80600054016000819055505b505600a165627a7a7230582010b5d4a1c4f8f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e4b4f4b4e0029",
"compiler_version": "0.3.7"
}"#;
let vyper_artifact: VyperArtifact = serde_json::from_str(vyper_json)?;
println!("\n=== Vyper合约 ===");
println!("编译器版本: {}", vyper_artifact.compiler_version);
println!("运行时字节码: {}", vyper_artifact.bytecode_runtime);
// 3. 生成新的合约编译产物
let new_contract = Contract {
abi: Some(vec![
serde_json::from_str(r#"{"inputs":[],"name":"get","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}"#)?
]),
evm: Bytecode {
bytecode: Some(BytecodeObject {
object: "0x6080604052348015600f57600080fd5b506004361060285760003560e01c80636d4ce63c14602d575b600080fd5b60336047565b6040518082815260200191505060405180910390f35b600080549050905600a165627a7a7230582042b0bb89d7e7e1e5b0f0b0e0b0f0b0e0b0f0b0e0b0f0b0e0b0f0b0e0b0f0b0e0029".to_string(),
..Default::default()
}),
deployed_bytecode: DeployedBytecode {
bytecode: Some(BytecodeObject {
object: "0x6080604052348015600f57600080fd5b506004361060285760003560e01c80636d4ce63c14602d575b600080fd5b60336047565b6040518082815260200191505060405180910390f35b600080549050905600a165627a7a7230582042b0bb89d7e7e1e5b0f0b0e0b0f0b0e0b0f0b0e0b0f0b0e0b0f0b0e0b0f0b0e0029".to_string(),
..Default::default()
}),
..Default::default()
},
..Default::default()
},
..Default::default()
};
println!("\n=== 生成的合约 ===");
println!("{}", serde_json::to_string_pretty(&new_contract)?);
Ok(())
}
维护团队
- alloy-rs/core团队
- Matthias Seitz
- DaniPopes
- Arsenii Kulikov
1 回复
Rust智能合约编译器工具foundry-compilers-artifacts使用指南
工具介绍
foundry-compilers-artifacts
是一个Rust库,专门用于高效解析和生成Solidity和Vyper智能合约的编译产物。它是Foundry工具链的一部分,主要用于处理智能合约编译后的JSON格式输出文件(artifacts)。
该工具的主要功能包括:
- 解析Solidity/Vyper合约编译后的JSON artifacts
- 生成标准化的合约编译产物
- 提供类型安全的Rust接口访问编译信息
- 支持合约ABI、字节码、部署字节码等关键信息的提取
安装方法
在Cargo.toml中添加依赖:
[dependencies]
foundry-compilers-artifacts = "0.1.0"
基本使用方法
1. 解析合约Artifacts
use foundry_compilers_artifacts::{Artifact, SolcArtifact};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 从文件读取artifacts
let artifact_json = std::fs::read_to_string("MyContract.json")?;
let artifact: SolcArtifact = serde_json::from_str(&artifact_json)?;
// 访问合约ABI
println!("Contract ABI: {:?}", artifact.abi);
// 访问字节码
if let Some(bytecode) = artifact.bytecode {
println!("Bytecode: {}", bytecode.object);
}
Ok(())
}
2. 生成Artifacts
use foundry_compilers_artifacts::{
ArtifactOutput, BytecodeObject, ContractBytecode, Settings, SolcArtifact
};
fn generate_artifact() -> SolcArtifact {
SolcArtifact {
abi: Some(vec![/* ABI条目 */]),
bytecode: Some(ContractBytecode {
object: BytecodeObject::new("0x6060..."),
// 其他字节码相关字段
}),
deployed_bytecode: Some(ContractBytecode {
object: BytecodeObject::new("0x6080..."),
// 其他部署字节码相关字段
}),
// 其他字段
..Default::default()
}
}
3. 处理多个合约
use foundry_compilers_artifacts::{Artifacts, SolcArtifact};
fn process_multiple_contracts(artifacts: Artifacts<SolcArtifact>) {
for (contract_name, artifact) in artifacts.into_contracts() {
println!("Processing contract: {}", contract_name);
if let Some(abi) = artifact.abi {
println!("ABI length: {}", abi.len());
}
// 处理字节码等其他信息
}
}
4. 与Vyper合约交互
use foundry_compilers_artifacts::VyperArtifact;
fn process_vyper_artifact(vyper_json: &str) {
let artifact: VyperArtifact = serde_json::from_str(vyper_json).unwrap();
println!("Vyper contract ABI: {:?}", artifact.abi);
println!("Vyper bytecode: {:?}", artifact.bytecode);
}
高级用法
1. 自定义Artifacts输出格式
use foundry_compilers_artifacts::{ArtifactOutput, Settings};
let settings = Settings {
additional_values: serde_json::json!({
"custom_field": "custom_value"
}),
// 其他设置字段
..Default::default()
};
let output = ArtifactOutput::new(artifact, settings);
let json = serde_json::to_string_pretty(&output)?;
2. 过滤和转换Artifacts
use foundry_compilers_artifacts::{Artifacts, SolcArtifact};
fn filter_contracts(artifacts: Artifacts<SolcArtifact>) -> Artifacts<SolcArtifact> {
// 过滤出以ERC20开头的合约
artifacts.into_contracts()
.filter(|(name, _)| name.starts_with("ERC20"))
.collect()
}
完整示例demo
以下是一个完整的示例,展示如何使用foundry-compilers-artifacts
处理多个合约artifacts:
use foundry_compilers_artifacts::{Artifacts, SolcArtifact};
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 读取目录中的所有合约artifacts
let artifacts_dir = Path::new("./artifacts");
let artifacts = Artifacts::<SolcArtifact>::read_from_dir(artifacts_dir)?;
// 2. 过滤出ERC20合约
let erc20_artifacts = artifacts.into_contracts()
.filter(|(name, _)| name.starts_with("ERC20"))
.collect::<Artifacts<SolcArtifact>>();
// 3. 处理每个ERC20合约
for (contract_name, artifact) in erc20_artifacts.into_contracts() {
println!("Processing ERC20 contract: {}", contract_name);
// 检查并打印ABI信息
if let Some(abi) = &artifact.abi {
println!(" ABI contains {} items", abi.len());
// 查找transfer函数
let has_transfer = abi.iter().any(|item| {
if let serde_json::Value::Object(obj) = item {
obj.get("name") == Some(&serde_json::Value::String("transfer".to_string())) &&
obj.get("type") == Some(&serde_json::Value::String("function".to_string()))
} else {
false
}
});
println!(" Has transfer function: {}", has_transfer);
}
// 检查并打印字节码信息
if let Some(bytecode) = &artifact.bytecode {
println!(" Bytecode length: {} bytes", bytecode.object.as_str().unwrap().len() / 2);
}
}
Ok(())
}
性能提示
- 对于大量合约处理,考虑使用
Artifacts::read_from_dir
而不是逐个文件读取 - 如果只需要部分信息(如仅ABI),可以使用
serde_json::Value
进行初步过滤后再解析 - 对于重复处理相同artifacts,可以考虑缓存解析结果
foundry-compilers-artifacts
为Rust开发者提供了强大而灵活的工具来处理智能合约编译产物,无论是构建开发工具、测试框架还是部署脚本,都能显著提高开发效率。