• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Rust 部署调用solidity智能合约

武飞扬头像
lfhuang@com
帮助1

前言

最近在学习Polkadot底层的substrate框架及moonbeam兼容以太坊的智能合约平台,为了更好的学习熟练Rust的语法编程,整理个Rust以太坊部署调用solidity智能合约的代码。当然正常项目开发还是使用Truffle、Hardhat等框架部署调用测试方便,偶尔使用Java写的单元测试对一些常见的标准合约调用也比rust方便😂

准备

1、使用自己的节点或者使用第三方的公共节点提供RPC地址
2、以太坊地址
3、这里使用BSC币安智能链测试网:https://bsc-testnet.public.blastapi.io

使用Cargo创建项目

cargo new deploy-contract

cd deploy-contract

请自行选用文本编辑器打开 Cargo.toml 文件。需要安装ethers.rs库等。

[package]
name = "deploy-contract"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
ethers = "1.0.2"
ethers-solc = "1.0.2"
tokio = { version = "1", features = ["full"] }
serde_json = "1.0.89"
serde = "1.0.149"

项目目录结构

├── Cargo.lock
├── Cargo.toml
├── target
├── src
    ├── Incrementer.sol
    └── main.rs
└── Incrementer_ABI.json

代码示例

main.rs

use ethers::prelude::*;
use ethers::providers::{Http, Provider};
use ethers_solc::Solc;
use std::{path::Path, sync::Arc};

type Client = SignerMiddleware<Provider<Http>, Wallet<k256::ecdsa::SigningKey>>;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let provider: Provider<Http> = Provider::<Http>::try_from("https://data-seed-prebsc-1-s1.binance.org:8545")?; // 替换你的RPC地址 http://127.0.0.1:8545
                                                                                         // 配置私钥,去除“0x”前缀
    let wallet: LocalWallet = "a58ac7ea54b74896c6a3129370dea99140c42b6908dff628f9062b9d40da4b7e"
        .parse::<LocalWallet>()?;
    let client = SignerMiddleware::new(provider.clone(), wallet.clone());

    // 部署合约
    let addr = compile_deploy_contract(&client).await?;
    //读取合约中的number值
    read_number(&client, &addr).await?;

    // 调用合约增加number值方法
    increment_number(&client, &addr).await?;
    read_number(&client, &addr).await?;

    // 重置合约中的number值
    reset(&client, &addr).await?;
    read_number(&client, &addr).await?;

    Ok(())
}

async fn compile_deploy_contract(client: &Client) -> Result<H160, Box<dyn std::error::Error>> {
    // Incrementer.sol source的变量作为托管所有需要编译的智能合约的目录路径,该目录为根目录
    let source = Path::new(&env!("CARGO_MANIFEST_DIR")); //设置环境变量,Cargo.toml 文件所在的文件夹路径
                                                         // let source = Path::new("/Users/smartstrategy-ios01/IT/Rust/rust-web3/deploy-contract");
    println!("source:{}", source.display());

    // 编译合约   需要先安装solc-select工具编译所有的智能合约:https://github.com/crytic/solc-select
    let compiled = Solc::default()
        .compile_source(source)
        .expect("Could not compile contracts");
    // println!("compiled:{:#?}",compiled);

    // 获取合约的abi和Bytecode文件
    let (abi, bytecode, _runtime_bytecode) = compiled
        .find("Incrementer")
        .expect("could not find contract")
        .into_parts_or_default();
    // let contract = compiled
    //     .get(
    //         "/Users/smartstrategy-ios01/IT/Rust/rust-web3/deploy-contract/src/Incrementer.sol",
    //         "Incrementer",
    //     )
    //     .expect("could not find contract");

    // println!("abi:{:#?}",abi);
    // println!("bytecode:{:#?}",bytecode);
    // println!("_runtime_bytecode:{:#?}",_runtime_bytecode);

    // 创建将用于部署合约的工厂实例
    let factory = ContractFactory::new(abi, bytecode, Arc::new(client.clone()));
    // let factory = ContractFactory::new(
    //     contract.abi.unwrap().clone(),
    //     contract.bytecode().unwrap().clone(),
    //     Arc::new(client.clone()),
    // );

    // let contract = factory
    //     .deploy(U256::from(5))?
    //     .confirmations(0usize)
    //     .legacy()
    //     .send()
    //     .await?;

    // 部署合约 初始构造参数100
    let contract = factory.deploy(U256::from(100))?.legacy().send().await?;
    let addr = contract.address(); //返回部署合约后地址

    println!("Incrementer.sol has been deployed to {:?}", addr);

    Ok(addr)
}

// 为Incrementer智能合约生成类型安全接口
abigen!(
    Incrementer,
    "./Incrementer_ABI.json",
    event_derives(serde::Deserialize, serde::Serialize)
);

async fn read_number(
    client: &Client,
    contract_addr: &H160,
) -> Result<U256, Box<dyn std::error::Error>> {
    // 创建合同实例
    let contract = Incrementer::new(contract_addr.clone(), Arc::new(client.clone()));

    // 调用合约中的number方法,查询值
    let value = contract.number().call().await?;

    println!("Incrementer's number is {}", value);

    Ok(value)
}

async fn increment_number(
    client: &Client,
    contract_addr: &H160,
) -> Result<(), Box<dyn std::error::Error>> {
    println!("Incrementing number...");

    // 创建合同实例
    let contract = Incrementer::new(contract_addr.clone(), Arc::new(client.clone()));

    // 调用合约increment方法,增加number值
    let tx = contract.increment(U256::from(100)).legacy().send().await?.await?;
    println!("Transaction Receipt: {}", serde_json::to_string(&tx)?);

    Ok(())
}

async fn reset(client: &Client, contract_addr: &H160) -> Result<(), Box<dyn std::error::Error>> {
    println!("Resetting number...");

    // 创建合同实例
    let contract = Incrementer::new(contract_addr.clone(), Arc::new(client.clone()));

    // 调用合约reset方法,重置number值
    let tx = contract.reset().legacy().send().await?.await?;
    println!("Transaction Receipt: {}", serde_json::to_string(&tx)?);

    Ok(())
}

Incrementer.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract Incrementer {
    uint256 public number;

    constructor(uint256 _initialNumber) {
        number = _initialNumber;
    }

    function increment(uint256 _value) public {
        number = number   _value;
    }

    function reset() public {
        number = 0;
    }
}

Incrementer_ABI.json

[
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_value",
        "type": "uint256"
      }
    ],
    "name": "increment",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "number",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "reset",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  }
]

构建并运行 Cargo 项目

使用 cargo run 一步构建并运行项目。

cargo run

控制台输出内容

AY:deploy-contract smartstrategy-ios01$ cargo run
   Compiling deploy-contract v0.1.0 (/Users/smartstrategy-ios01/IT/Rust/rust-web3/deploy-contract)
    Finished dev [unoptimized   debuginfo] target(s) in 9.54s
     Running `target/debug/deploy-contract`
source:/Users/smartstrategy-ios01/IT/Rust/rust-web3/deploy-contract
Incrementer.sol has been deployed to 0x069678ed1155adaf5acb44ad45602fa3ebd7dd78
Incrementer's number is 100
Incrementing number...
Transaction Receipt: {"transactionHash":"0xe6afff8ec5e4e2bdc38ce579ebff1b148f3000953da6af92e0f1215334c1860b","transactionIndex":"0x6","blockHash":"0x3888b24555e43fcb400535985dc9c0b900a7aa9b273f764c00dbc053eac75f8d","blockNumber":"0x1a0c789","from":"0x9295b5ca66cc2d8abfa9024f482038a2d5ff7eaf","to":"0x069678ed1155adaf5acb44ad45602fa3ebd7dd78","cumulativeGasUsed":"0xa33a8","gasUsed":"0x6bc6","contractAddress":null,"logs":[],"status":"0x1","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","type":"0x0","effectiveGasPrice":"0x2540be400"}
Incrementer's number is 200
Resetting number...
Transaction Receipt: {"transactionHash":"0xbe05fcfef36f760a2dbf0979d84b264d4248976d06a96ed934a29c7940f55dff","transactionIndex":"0x7","blockHash":"0x720670bedd5c2c145ecc37a3a6a8fa31a0fa27ce24e1e21f2c5fc7a6f65689bf","blockNumber":"0x1a0c78d","from":"0x9295b5ca66cc2d8abfa9024f482038a2d5ff7eaf","to":"0x069678ed1155adaf5acb44ad45602fa3ebd7dd78","cumulativeGasUsed":"0x12c694","gasUsed":"0x3342","contractAddress":null,"logs":[],"status":"0x1","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","type":"0x0","effectiveGasPrice":"0x2540be400"}
Incrementer's number is 0

区块浏览器

hash:https://testnet.bscscan.com/tx/0x23b1bf144342b5cfcb7ede10e87b90185f499eec4af6877afee7d956e4036145

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgcjhef
系列文章
更多 icon
同类精品
更多 icon
继续加载