当前位置: 首页 > news >正文

探究与以太坊智能合约的交互

# 概述
智能合约是部署在区块链上的一串代代码,通常我们与智能合约的打交道 可以通过前端的Dapp,etherscan,metamask 等方式。作为开发人员可以通过调用提供的相关包来与之交互,如web3.js,ether.js , web3.j(java 语言的包)。那么能否绕过这些东西直接与链发生交互呢?当然可以!
首先来了解第一个概念,区块链节点
任何一台计算机(能联网,且配置够),都可以启动以太坊的客户端来加入区块链,加入后这个节点会同步整个链上的状态,即通过这个节点就可以获取整个链的状态以及通过这个节点可以改变的状态。
第二个,智能合约。简而言之,智能合约是在节点上部署的代码,用户调用时会在节点上执行。
第三个,jsonrpc。jsonrpc 是一个远程调用的协议规范,规定了交互时的入参和出参的格式要求。[jsonrpc中文文档](https://wiki.geekdream.com/Specification/json-rpc_2.0.html)

后面以这个,合约代码为示例演示交互
```javascript
// SPDX-License-Identifier: MIT
pragma solidity =0.8.4;

contract Test {
    uint256 private value;


    function setValue(uint256 _value) public {
        value = _value;
    }

    function getValue() public view returns(uint256){
        return value;
    }
    
}

```


### 使用remix 与合约交互

![[Pasted image 20220402114639.png]]

通过 remix 部署后会出现,可以调用的函数名。这种是最基础的用法

但是当页面刷新后,左下角的可调用的函数名就没了,这种情况下就需要使用 At Address这个按钮了
![[Pasted image 20220402120058.png]]


在代码框只需要提供要调用合约方法的接口,再将要调用的合约放入 At Address的框里,点击按钮,就会出现接口中的方法。这种就是不要合约的实现,只知道方法接口和地址就可以调用了。
合约调用的最核心就是两个东西,一个是部署后的合约地址,另外一个就要方法的接口也就是ABI


### 使用ethscan 与智能合约交互
另外一种与合约交互的方式,是通过ethscan。这种的前提是,合约代码已经在ethscan上进行开源过了。
![[Pasted image 20220402135533.png]]

其中 Read Contact 是读方法,不需要消耗gas.
Write Contact 是写方法,调用这些方法会改变链上的状态,会消耗gas.

### 使用web3.js 与合约交互
再有就是通过web3.js 的库进行交互
```javascript
var fs = require('fs');

var Web3 = require('web3');

const infuraKey = fs.readFileSync("../.infuraKey").toString().trim();

var ethRpcUrl = `https://rinkeby.infura.io/v3/`+infuraKey

var web3 = new Web3(ethRpcUrl);

  

abi = [

{

"inputs": [],

"name": "getValue",

"outputs": [

{

"internalType": "uint256",

"name": "",

"type": "uint256"

}

],

"stateMutability": "view",

"type": "function"

},

{

"inputs": [

{

"internalType": "uint256",

"name": "_value",

"type": "uint256"

}

],

"name": "setValue",

"outputs": [],

"stateMutability": "nonpayable",

"type": "function"

}

]

address = "合约地址"

pk = "钱包私钥"

  

main()

    .then(() => process.exit(0))
    
    .catch(error => {
    
    console.error(error);
    
    process.exit(1);

});

  

async function getValue(){

    var contract = new web3.eth.Contract(abi, address);
    
    var value = await contract.methods.getValue().call();
    
    console.log(value);

}

  
  

async function setValue(){

    value = 123
    
    var contract = new web3.eth.Contract(abi, address);
    
    var encodeABI = await contract.methods.setValue(value).encodeABI();
    
    var signResult = await web3.eth.accounts.signTransaction({
    
    gas: 3000000,
    
    to: address,
    
    data: encodeABI
    
    }, pk);
    
    console.log(signResult);
    
    var result = await web3.eth.sendSignedTransaction(signResult.rawTransaction);
    
    console.log(result);
    
      

}

  

async function main(){

    await setValue();
    
    await getValue();

}
```


### 使用http 请求与智能合约交互
[ethreum json rpc API](https://eth.wiki/json-rpc/API)

https://eth.wiki/json-rpc/API
上面这几种方式都是比较常规的,接下展示一种非常规的操作,即通过http请求来交互

```javascript
var fs = require('fs');

const fetch = require('node-fetch')

var Web3 = require('web3');

const ethers = require('ethers');

const infuraKey = fs.readFileSync("../.infuraKey").toString().trim();

var ethRpcUrl = `https://rinkeby.infura.io/v3/`+infuraKey

var web3 = new Web3(ethRpcUrl);

abi = [

{

"inputs": [],

"name": "getValue",

"outputs": [

{

"internalType": "uint256",

"name": "",

"type": "uint256"

}

],

"stateMutability": "view",

"type": "function"

},

{

"inputs": [

{

"internalType": "uint256",

"name": "_value",

"type": "uint256"

}

],

"name": "setValue",

"outputs": [],

"stateMutability": "nonpayable",

"type": "function"

}

]

contractAddress = "合约地址"

pk = "钱包私钥"

userAccount = "私钥对应的账户地址"

main()

.then(() => process.exit(0))

.catch(error => {

console.error(error);

process.exit(1);

});

  

async function main(){

    await setValue();
    
    await getValue();

}

  
  

async function getNonce(account){

    let nonce = await web3.eth.getTransactionCount(account);
    
    console.log('nonce = ', nonce)
    
    return nonce;

}

  

async function getValue(){

    // 对方法进行sha3编码,然后取前四个字节
    
    // var methodSign = await web3.utils.keccak256("getValue()").substr(0, 10);
    
    var methodSign = await web3.utils.keccak256("getValue()").substr(0, 10);
    
      
    
    // console.log(methodSign)
    
    data = methodSign;
    
    // 如果有入参,对入参进行编码
    
    // encodeParams = web3.eth.abi.encodeParameters(['uint256'],[456]);
    
    // 拼接方法名和入参作为jsonrpc的 params中的data字段的数据
    
    // data +=encodeParams.substr(2,encodeParams.length)
    
    console.log(data)
    
    // 构造post 请求的body参数
    
    var input = {"jsonrpc":"2.0","id":3,"method":"eth_call","params":[{"to":contractAddress,"data":data},"latest"]}
    
    // http 可以一次多个请求
    
    var inputs = [input,input]
    
    // 发送post请求
    
    const resp = await fetch(ethRpcUrl, {
    
        method: "POST",
        
        body: JSON.stringify(inputs),
        
        headers: {
        
        "Content-Type": "application/json"
    
    }
    
    });
    
    var rpcResult = await resp.json();
    
    console.log(rpcResult[0].result)
    
    // 用 ethers包中的方法解析返回结果
    
    var ethersResult = await ethers.utils.defaultAbiCoder.decode(['uint256'], rpcResult[0].result)
    
    // 用 web3包中的方法解析防护结果
    
    var decodeResult = await web3.eth.abi.decodeParameters(['uint256'], rpcResult[0].result);
    
    console.log("vaule is "+ethersResult)
    
    console.log("value is "+decodeResult[0])

  

}

  

async function setValue(){

    // 这里借用web3的方法对要发送的内容进行签名
    var contract = new web3.eth.Contract(abi, contractAddress);
    
    value = 456;
    
    var encodeABI = contract.methods.setValue(value).encodeABI();
    
    var signResult = await web3.eth.accounts.signTransaction({
    
    gas: 3000000,
    
    to: contractAddress,
    
    data: encodeABI,
    
    nonce: await getNonce(userAccount)
    
    }, pk);
    
    console.log(signResult);
    
    rawTransaction = signResult.rawTransaction
    
    // 构造post 请求的body参数
    
    var input = {"jsonrpc":"2.0","id":3,"method":"eth_sendRawTransaction","params":[rawTransaction]}
    
    console.log(input)
    
    var inputs = [input]
    
    // 发送post请求
    
    const resp = await fetch(ethRpcUrl, {
    
        method: "POST",
        
        body: JSON.stringify(inputs),
        
        headers: {
        
        "Content-Type": "application/json"
        
        }
    
    });
    
    var rpcResult = await resp.json();
    
    console.log(rpcResult)

}

```

通过jsonrpc 方式,可以更灵活的与合约进行交互,只要拿到别人的签名信息,只发http请求就可以和链进行交互,至于是谁发送的这个http,就关系不大了。


## 综述
不管是remix 、etherscan 还是web3.js 这几种方式,本质上都是对jsonrpc方法封装。理解它们的底层交互逻辑,可以让我们更深刻的认识这些技术,从而发现它们还是我们日常使用的http请求,也就没有那么神秘了。
 

相关文章:

探究与以太坊智能合约的交互

# 概述 智能合约是部署在区块链上的一串代代码,通常我们与智能合约的打交道 可以通过前端的Dapp,etherscan,metamask 等方式。作为开发人员可以通过调用提供的相关包来与之交互,如web3.js,ether.js , web3.j(java 语言…...

Windows如何安装docker-desktop

下载 docker-desktop设置环境安装wsl可能遇到的错误 下载 docker-desktop 下载官网:https://www.docker.com/products/docker-desktop/ 设置环境 如果没有Hyper-V选项的,按照以下步骤 添加一个文件Hyper-V.bat 添加以下内容,并双击运行后重启电脑 pushd "%~…...

芯片设计后端遇到的各种文件类型和文件后缀

芯片设计后端遇到的各种文件类型和文件后缀 文件类型 描述 文件后缀 netlist网表文件 verilog文件格式,记录了芯片里各个instance的逻辑连接关系 .v (for Verilog netlists) Lib,liberty timing file 记录了cell的timing信息及一定power信息。有的…...

【Web】Java反序列化之CC7链——Hashtable

目录 链子原理分析(借尸还魂) 如何构造相等hash 又谈为何lazyMap2.remove("yy") 不过真的需要两个LazyMap吗 EXP 双LazyMap exp HashMap&LazyMap exp 链子原理分析(借尸还魂) 先看Hashtable#readObject origlength和elements分别是原始数组的长度和元素…...

NumPy数据处理详解的笔记2

NumPy数据处理详解的笔记2 第1章NumPy基础 NumPy是用于处理多维数组的数值运算库,不仅可用于 机器学习,还可以用于图像处理,语言处理等任务。 1.2 多维数据结构ndarray的基础 在学习NumPy的过程中,只要理解了ndarray的相关知识…...

xsslabs第四关

测试 "onclick"alert(1) 这与第三关的代码是一样的&#xff0c;但是每一关考的点是不一样的所以我们看一下源代码 <!DOCTYPE html><!--STATUS OK--><html> <head> <meta http-equiv"content-type" content"text/html;ch…...

Qt下使用modbus-c库实现PLC线圈/保持寄存器的读写

系列文章目录 提示&#xff1a;这里是该系列文章的所有文章的目录 第一章&#xff1a;Qt下使用ModbusTcp通信协议进行PLC线圈/保持寄存器的读写&#xff08;32位有符号数&#xff09; 第二章&#xff1a;Qt下使用modbus-c库实现PLC线圈/保持寄存器的读写 文章目录 系列文章目录…...

C++ 滑动窗口

例1 209. 长度最小的子数组 ①窗口大小不固定 ②求最小长度 -> ret INT_MAX ③数组内的值都大于0&#xff0c; 符合单调性&#xff08;sum nums[right] -> sum增大&#xff09; while里面符合条件&#xff0c;在里面更改ret 参考代码 class Solution { public:i…...

【深度学习】TensorFlow基础介绍

TensorFlow 模型 张量、变量共同点&#xff1a;具有形状、类型、值等3个属性。 不同点&#xff1a;变量可被TensorFlow的自动求导机制求导&#xff0c;常被用于机器学习模型的参数。 tfrecord tensorflow定义的数据格式&#xff0c;一种二进制文件格式&#xff0c;用于保存…...

springcloud:3.3测试重试机制

服务提供者【test-provider8001】 Openfeign远程调用服务提供者搭建 文章地址http://t.csdnimg.cn/06iz8 相关接口 测试远程调用&#xff1a;http://localhost:8001/payment/index 服务消费者【test-consumer-resilience4j8004】 Openfeign远程调用消费者搭建 文章地址http:/…...

【笔记】【电子科大 离散数学】 3.谓词逻辑

谓词引入 因为含变量的语句&#xff08;例如x > 3&#xff09;不是命题&#xff0c;无法进行逻辑推理。 为了研究简单命题句子内部的逻辑关系&#xff0c;我们需要对简单命题进行分解&#xff0c;利用个体词&#xff0c;谓词和量词来描述它们&#xff0c;并研究个体与总体…...

倍增算法C++

倍增 倍增算法是一种优化算法&#xff0c;通常用于某些需要高效计算指数幂的场景。它基于分治的思想&#xff0c;通过反复求平方来实现快速计算指数幂的目的。在实际应用中&#xff0c;倍增算法经常用于解决最近公共祖先问题、二分查找等。 1、快速幂详解 ksm核心代码 倍增就是…...

uniapp制作--进步器的选择

介绍&#xff1a; 进步器的选择,一般用于商城购物选择物品数量的场景 注意&#xff1a;该输入框只能输入大于或等于0的整数 效果展示&#xff1a; 代码展示&#xff1a; 以下是一个简单的购物车页面示例&#xff0c;包括选择商品和显示数量的功能&#xff1a; 在这个示例中…...

前端高频面试--查缺补漏篇

什么是进程和线程&#xff0c;有什么区别 进程&#xff1a;进程是程序的一次执行过程&#xff0c;是动态的过程&#xff0c;有自身产生、存在、消亡的过程。 线程&#xff1a;线程由进程创建&#xff0c;是进程的一个实体。一个进程可以拥有多个线程。 举个例子&#xff1a;…...

【计算机学习】-- 网页视频加速

系列文章目录 文章目录 系列文章目录前言一、开发者选项二、定义和用法1.基础语法&#xff1a;2.什么是uncaught TypeError:Cannot read properties of null? 二、开发者工具面板&#xff1a;1.Elements面板&#xff1a;2.Console面板&#xff1a; 总结 前言 一、开发者选项 …...

系统运维-Linux配置C、C++、Go语言编译环境

C yum install gcc -y #安装gcc编译器 gcc --version #验证环境gcc (GCC) 11.3.1 20221121 (Red Hat 11.3.1-4) Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even f…...

【设计模式】(二)设计模式六大设计原则

一、 设计原则概述 设计模式中主要有六大设计原则&#xff0c;简称为SOLID &#xff0c;是由于各个原则的首字母简称合并的来(两个L算一个,solid 稳定的)&#xff0c;六大设计原则分别如下&#xff1a; ​ 1、单一职责原则&#xff08;Single Responsibitity Principle&#…...

go-zero官网

go-zero 是一个集成了各种工程实践的 web 和 rpc 框架。通过弹性设计保障了大并发服务端的稳定性&#xff0c;经受了充分的实战检验。 go-zero官网&#xff1a;go-zero 缩短从需求到上线的距离...

Redis的应用场景以及常见问题(持续更新)

一、使用场景 1&#xff0c;在大型的秒杀库存扣减&#xff0c;app首页流量高峰&#xff0c;很容易将传统的关系型数据库&#xff08;mysql,oracle等&#xff09;给压垮 2&#xff0c;还有很多没必要持久化的数据&#xff0c;比如说短信验证码&#xff0c;点赞数等 3&#xff0c…...

前端添加压缩包内文件名称校验

1. tar包内文件名称校验 1. 读取tar包内所有的文件名称 export class TarReader {fileInfo: any[]buffer: string | ArrayBufferconstructor() {this.fileInfo []}readFile(file) {return new Promise(resolve > {const reader new FileReader()reader.onload event &g…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...

算术操作符与类型转换:从基础到精通

目录 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符&#xff1a;、-、*、/、% 赋值操作符&#xff1a;和复合赋值 单⽬操作符&#xff1a;、--、、- 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...