【无标题】

这里写自定义目录标题

使用Rust直接编译单个的Solidity合约

前言

我们知道,我们平常开发Solidity智能合约时一般使用Hardhat框架,但是如果你是一个Rustacean (这是由 "Rust" 和 "crustacean" -甲壳类动物 结合而来的俏皮称呼),也许你会使用Foundry框架进行开发。开发好了之后,我们要编写相关应用怎么办?通常的做法是将编译好的合约字节码和ABI复制到其它项目中去,然后使用各种框架来编写我们的Dapp。

但是这里有一个问题,如果合约只是简单的合约,或者是一个flatten之后的合约,如果有任何修改,你都必须在Hardhat或者Foundry中进行重新编译,然后重复复制到Dapp目录(偷懒的做法是使用一个sh 脚本自动去做这些事)。那么,作为一个Rustacean来讲,你肯定在想,能否在我的Dapp中使用Rust语言来直接编译这个合约呢?答案是肯定的。

这样做的目的是为我们节省不少工序,如果只是一个简单的没有外部依赖的合约,或者是一个Flatten后的合约,我们直接在Dapp目录进行开发和编译及使用其它库进行交互,不必重新建立hardhat或者foundry工程。

但是这是有前提的,我们直接使用Rust编译并不会自动查找它的外部依赖,因此这是我说的只能编译简单合约或者flatten合约的原因。

预备知识

Rust 语言本身无法编译Solidity或者Vyper智能合约,因此它还是得调用第三方编译工具进行。通常这个工具为solc。其原理就是Rust调用solc,再由solc来编译合约。

但是Rust调用solc这一步已经有第三方库抽象好了,我们不必手动去实现了。

在我们的示例中,我们使用 foundry-compilers这个crate来调用solc进行编译,它其实是Foundry内部工具的一部分。

准备工作

上面提到了,还是得第三方编译工具。因此我们得安装solc,具体方法为:

bash 复制代码
brew install solc-select
solc-select install 0.8.24
solc-select use 0.8.24

示例

  1. 运行cargo new sol_demo 来新建一个rust 工程

  2. 在项目根目录下建立contracts目录,这是hardhat框架常用的源文件目录。

  3. contracts目录下新建Counter.sol,内容如下:

    solidity 复制代码
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.24;
    contract Counter {
    	uint256 public number;
    
    	function setNumber(uint256 newNumber) public {
        	number = newNumber;
    	}
    
    	function increment() public {
        	number++;
    	}
    }
  4. Cargo.toml中添加如下依赖

    toml 复制代码
    [dependencies]
    foundry-compilers = "0.11.0"
  5. main.rs替换为如下内容:

    rust 复制代码
    use foundry_compilers::{Project, ProjectPathsConfig};
    use std::path::Path;
    use std::env;
    fn main() {
    	// 这个环境变量会识别为运行cargo的项目根目录
    	let cargo_manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    	// configure the project with all its paths, solc, cache etc.
    	let project = Project::builder()
    		.paths(ProjectPathsConfig::hardhat(Path::new(&cargo_manifest_dir)).unwrap())
    		.build(Default::default()) //Default::default()这里其实返回的是MultiCompilers,可以编译vyper和solidity
    	    .unwrap();
    	// 这里也可以使用compile()函数编译contracts目录下的所有文件,有外部依赖的得提前导入
    	let output = project.compile_file("contracts/Counter.sol").unwrap();
    	// 如果有任何错误,panic
    	output.succeeded();
    	println!("Compilation succeeded.");
    	// Tell Cargo that if a source file changes, to rerun this build script.
    	// project.rerun_if_sources_changed();
    }
  6. 打开终端,在项目根目录下运行cargo run,得到Compilation succeeded.输出。

  7. 同时查看项目根目录,会发现多了artifactscache目录,如下图所示:

真正使用时,你其实是另外起一个bin目录,在这里面做编译工作,而主main.rs一般做交互工作。

相关推荐
中金快讯6 小时前
数字人民币杠杆破局预付乱象 XBIT智能合约筑牢资金安全防线
安全·智能合约
夕水10 小时前
自动化按需导入组件库的工具rust版本完成开源了
前端·rust·trae
s91236010111 小时前
Rust Ubuntu下编译生成环境win程序踩坑指南
windows·ubuntu·rust
s91236010112 小时前
Rust std::thread::spawn(move) 的作用
开发语言·后端·rust
苏近之1 天前
深入理解 Rust 中的生命周期
rust
UestcXiye1 天前
Rust 学习笔记:编程练习(一)
rust
gambool1 天前
uniswap getTickAtSqrtPrice 方法解析
区块链·智能合约
高峰君主2 天前
WebAssembly全栈革命:在Rust与JavaScript之间构建高性能桥梁
javascript·rust·wasm
爱的叹息2 天前
解决 Dart Sass 的旧 JS API 弃用警告 的详细步骤和解决方案
javascript·rust·sass
这个懒人2 天前
使用 Truffle 和 Ganache 搭建本地以太坊开发环境并部署一个简单智能合约
智能合约