Hardhat编写、编译、部署、测试Solidity ERC20合约 - 进阶篇 - web3.js调用合约方法
1. Remix编写、编译、部署、测试Solidity ERC20合约 - 基础篇
2. Remix编写、编译、部署、测试Solidity ERC20合约 - 进阶篇
3. Hardhat编写、编译、部署、测试Solidity ERC20合约 - 基础篇
4. JSON-RPC调用区块链方法
5. JSON-RPC调用合约方法
6. JSON-RPC给合约账户同时转以太币和代币
7. web3.js调用区块链方法
8. web3.js调用合约方法
9. web3.js给合约账户同时转以太币和代币
10. Go-Ethereum调用区块链方法
11. Go-Ethereum调用合约方法
12. sendTransaction和sendRawTransaction区别
13. Metamask导入代币,转账ETH,转账代币 - 界面操作
14. Metamask连接hardhat本地节点
15. DAPP react界面-web3.js库-Metemask调用和显示-调用合约方法
16. web3js结合sepolia测试网
17. 总结
对比系列中的此篇文章
7. JSON-RPC调用合约方法
5. web3.js调用区块链方法
1. 以太坊通信协议
2. 编写调试代码
合约代码
基于ERC20的智能合约
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.4.0
pragma solidity ^0.8.27;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor() ERC20("MyToken", "MTK") payable {
_mint(msg.sender, 100 * 10 ** decimals());
}
fallback() external payable { }
receive() external payable { }
}
读操作用eth_call,写操作用eth_sendTransaction。
读操作,将method赋值给eth_call。合约地址放入to,方法名和参数放入data,赋值给params,组装jsonrpc。
读操作不消耗gas,从本地节点直接返回,不组装交易结构,不进行挖矿。所以不需要交易结构中的from、value、gaslimit、gasprice。
写操作消耗gas,广播到区块链上的节点,组装交易结构,进行挖矿。所以需要交易结构中的from、gaslimit、gasprice,默认不需要value。
web3.js在构造合约对象时,已经持有合约地址
const contract = new web3.eth.Contract(abi, contractAddress);
查询代币名称的JSON-RPC结构:
web3.js的调用方式:
await contract.methods.name().call()
底层构建的JSON-RPC结构:
{
jsonrpc: '2.0',
method: 'eth_call',
params: [{
to: contractAddress,
data: keccak256(Buffer.from('name()')).slice(0, 10)
}, 'latest'],
id: 1
}
查询余额的JSON-RPC结构:
web3.js的调用方式:
await contract.methods.balanceOf(accountAddr).call()
底层构建的JSON-RPC结构:
{
jsonrpc: '2.0',
method: 'eth_call',
params: [{
to: contractAddress,
data: keccak256(Buffer.from('balanceOf(address)')).slice(0, 10) + accountAddr.toLowerCase().replace('0x', '').padStart(64, '0')
}, 'latest'],
id: 1
}
转账的JSON-RPC结构:
web3.js的调用方式:
await contract.methods.transfer(recAccountAddr, value).send({from: sendAccountAddr, gas: 3000000});
底层构建的JSON-RPC结构:
{
jsonrpc: '2.0',
method: 'eth_sendTransaction',
params: [{
from: sendAccountAddr,
to: contractAddr,
data: keccak256(Buffer.from('transfer(address,uint256)')).slice(0, 10) + recAccountAddr.toLowerCase().replace('0x', '').padStart(64, '0') + BigInt(value).toString(16).padStart(64, '0'),
gas: '0x300000'
}],
id: 1
}
总结一下,web3.js的设计逻辑是:
1. method字段由.call()和.send()决定。读操作用.call(),赋值'eth_call',写操作用.send(),赋值'eth_sendTransaction'。
2. params字段中的第一个元素是交易结构对象,to属性是合约地址,data属性是合约中方法和参数。通过const contract = new web3.eth.Contract(abi, contractAddress)来组装。
3. 编写调试代码
const { ethers } = require("hardhat");
const { default: Web3 } = require('web3');
const fs = require('fs');
const path = require('path');
const fromAddress = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266';
const toAddress = '0x70997970C51812dc3A010C7d01b50e0d17dc79C8';
// 部署合约
async function deploy() {
// 获取合约工厂(这里期望存在名为 Token 的合约,位于 contracts/ 下)
// 注意:合约名需与 solidity 文件中合约名一致。
const myContract = await ethers.getContractFactory("MyToken");
const token = await myContract.deploy();
// 等待链上确认
await token.waitForDeployment();
const address = await token.getAddress();
console.log("实际合约地址:", address);
return address;
}
// web3js调用合约方法
async function web3js(contractAddress) {
// 读取编译生成的合约 ABI 文件
const artifact = JSON.parse(fs.readFileSync(path.join(__dirname, '../../artifacts/contracts/Lock.sol/MyToken.json'), 'utf8'));
const abi = artifact.abi;
// 连接本地区块链节点
const web3 = new Web3("http://localhost:8545");
// web3.js 合约实例
const contract = new web3.eth.Contract(abi, contractAddress);
// ERC20 name, symbol, totalSupply, decimals, balanceOf方法
var name = await contract.methods.name().call();
console.log("Token Name:", name);
var symbol = await contract.methods.symbol().call();
console.log("Token Symbol:", symbol);
console.log("发送前MTK:", await contract.methods.balanceOf(fromAddress).call() / BigInt(1e18));
console.log("接收前MTK:", await contract.methods.balanceOf(toAddress).call() / BigInt(1e18));
// ERC20 transfer方法
var receipt = await contract.methods.transfer(toAddress, web3.utils.toWei(10, 'ether')).send({from: fromAddress, gas: 3000000});
console.log("发送后MTK:", await contract.methods.balanceOf(fromAddress).call() / BigInt(1e18));
console.log("接收后MTK:", await contract.methods.balanceOf(toAddress).call() / BigInt(1e18));
}
async function main() {
var address = await deploy();
console.log("web3js 调用合约方法:");
await web3js(address);
}
main().then();
4. 安装依赖
npm install web3
5. 启动Hardhat本地节点
npx hardhat node

6. 调试
npx hardhat run ignition\modules\Mytoken.js --network localhost

hardhat node输出

转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/tianma2012/article/details/156340960




