Explore the interactive calls with Ethereum smart contracts

overview

A smart contract is a series of codes deployed on the blockchain. Usually, we can deal with smart contracts through the front-end Dapp, etherscan, metamask, etc. As a developer, you can interact with it by calling the relevant packages provided, such as web3.js, ether.js, web3.j (java language package). So can these things be bypassed and interact directly with the chain? sure! First of all, let’s understand the first concept. Any computer of the blockchain node (can be connected to the Internet and have sufficient configuration) can start the client of Ethereum to join the blockchain. After joining, this node will synchronize the state of the entire
chain
, that is, through this node, the state of the entire chain and the state that can be changed through this node can be obtained.
Second, smart contracts. In short, a smart contract is a code deployed on a node, which will be executed on the node when the user invokes it.
The third one, jsonrpc. jsonrpc is a protocol specification for remote calls, which specifies the format requirements for input and output parameters during interaction.
jsonrpc Chinese document

Later, this contract code will be used as an example to demonstrate the interaction

// 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;
    }
    
}

Use remix to interact with contracts

insert image description here

After deploying through remix, the name of the function that can be called will appear. This is the most basic usage

But when the page is refreshed, the callable function name in the lower left corner is gone. In this case, you need to use the button At Address
![[Pasted image 20220402120058.png]]

In the code box, you only need to provide the interface to call the contract method, and then put the contract to be called into the At Address box, click the button, and the method in the interface will appear. This kind does not require the implementation of the contract, only knowing the method interface and address can be called.
The core of the contract call is two things, one is the contract address after deployment, and the other is the interface that requires the method, which is the ABI

Use ethscan to interact with smart contracts

Another way to interact with contracts is through ethscan. The premise of this is that the contract code has been open sourced on ethscan.
![[Pasted image 20220402135533.png]]

Among them, Read Contact is a reading method and does not need to consume gas.
Write Contact is a writing method. Calling these methods will change the state of the chain and consume gas.

Interact with contracts using web3.js

Then there is interaction through the web3.js library

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();

}

Interact with smart contracts using http requests

ethreum json rpc API

The above methods are relatively conventional, and then an unconventional operation is shown, that is, interaction through http requests

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)

}

Through the jsonrpc method, you can interact with the contract more flexibly. As long as you get someone else's signature information, you can interact with the chain only by sending an http request. As for who sent the http, it doesn't matter much.

review

Whether it is remix, etherscan or web3.js, these methods are essentially encapsulation of the jsonrpc method. Understanding their underlying interaction logic can give us a deeper understanding of these technologies, so that they are still http requests we use every day, so they are not so mysterious.

Guess you like

Origin blog.csdn.net/qq_36838406/article/details/123921578