千夫长 發表於 2024-9-20 14:28:10

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

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>使用Rust直接编译单个的Solidity合约</li><ul class="second_class_ul"><li>前言</li><li>预备知识</li><li>准备工作</li><li>示例</li></ul></ul></div><p class="maodian"></p><h2>使用Rust直接编译单个的Solidity合约</h2>
<p class="maodian"></p><h3>前言</h3>
<p>我们知道,我们平常开发Solidity智能合约时一般使用Hardhat框架,但是如果你是一个Rustacean (这是由 &ldquo;Rust&rdquo; 和 &ldquo;crustacean&rdquo; -甲壳类动物 结合而来的俏皮称呼),也许你会使用Foundry框架进行开发。开发好了之后,我们要编写相关应用怎么办?通常的做法是将编译好的合约字节码和ABI复制到其它项目中去,然后使用各种框架来编写我们的Dapp。</p>
<p>但是这里有一个问题,如果合约只是简单的合约,或者是一个flatten之后的合约,如果有任何修改,你都必须在Hardhat或者Foundry中进行重新编译,然后重复复制到Dapp目录(偷懒的做法是使用一个sh 脚本自动去做这些事)。那么,作为一个Rustacean来讲,你肯定在想,能否在我的Dapp中使用Rust语言来直接编译这个合约呢?答案是肯定的。</p>
<p>这样做的目的是为我们节省不少工序,如果只是一个简单的没有外部依赖的合约,或者是一个Flatten后的合约,我们直接在Dapp目录进行开发和编译及使用其它库进行交互,不必重新建立hardhat或者foundry工程。</p>
<p>但是这是有前提的,我们直接使用Rust编译并不会自动查找它的外部依赖,因此这是我说的只能编译简单合约或者flatten合约的原因。</p>
<p class="maodian"></p><h3>预备知识</h3>
<p>Rust 语言本身无法编译Solidity或者Vyper智能合约,因此它还是得调用第三方编译工具进行。通常这个工具为solc。其原理就是Rust调用solc,再由solc来编译合约。<br />但是Rust调用solc这一步已经有第三方库抽象好了,我们不必手动去实现了。<br />在我们的示例中,我们使用 <code>foundry-compilers</code>这个<code>crate</code>来调用<code>solc</code>进行编译,它其实是<code>Foundry</code>内部工具的一部分。</p>
<p class="maodian"></p><h3>准备工作</h3>
<p>上面提到了,还是得第三方编译工具。因此我们得安装solc,具体方法为:</p>
<div class="jb51code"><pre class="brush:plain;">brew install solc-select
solc-select install 0.8.24
solc-select use 0.8.24</pre></div>
<p class="maodian"></p><h3>示例</h3>
<p>运行<code>cargo new sol_demo</code> 来新建一个rust 工程</p>
<p>在项目根目录下建立<code>contracts</code>目录,这是hardhat框架常用的源文件目录。</p>
<p>在<code>contracts</code>目录下新建<code>Counter.sol</code>,内容如下:</p>
<div class="jb51code"><pre class="brush:plain;">// 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++;
        }
}</pre></div>
<p>在<code>Cargo.toml</code>中添加如下依赖</p>
<div class="jb51code"><pre class="brush:plain;">
foundry-compilers = "0.11.0"</pre></div>
<p>将<code>main.rs</code>替换为如下内容:</p>
<div class="jb51code"><pre class="brush:plain;">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(&amp;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();
}</pre></div>
<p>打开终端,在项目根目录下运行<code>cargo run</code>,得到<code>Compilation succeeded.</code>输出。</p>
<p>同时查看项目根目录,会发现多了<code>artifacts</code>和<code>cache</code>目录,如下图所示:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202409/20240920142533139.png" /></p>
<p>真正使用时,你其实是另外起一个bin目录,在这里面做编译工作,而主<code>main.rs</code>一般做交互工作。</p>
<p>到此这篇关于如何使用Rust直接编译单个的Solidity合约的文章就介绍到这了,更多相关Rust Solidity合约内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>Solidity可支付函数使用示例详解</li><li>使用ethers.js部署Solidity智能合约的方法</li><li>Solidity&nbsp;变量详解之类型、作用域与最佳实践记录</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: 如何使用Rust直接编译单个的Solidity合约