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. 总结
1. 编写调试代码
1.1 合约代码
ERC20只转代币,不用来转ETH,这里只是来讲解如何同时操作。
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20
{
constructor() ERC20("MyToken", "MTK")
{
_mint(msg.sender, 100 * 10 ** 18);
}
// 转账ETH和MTK
function transferETH_MTK(address to, uint256 value) external payable
{
// 转账ETH
payable(to).transfer(msg.value);
// 转账MTK
transfer(to, value);
}
receive() external payable {}
}
payable(to).transfer(msg.value); 是以太坊 Solidity 智能合约中向指定地址转账以太币的标准写法
transfer(to, value);是ERC20的方法

1.2 调试代码
转账的JSON-RPC结构:
web3.js的调用方式:
await contract.methods.transferETH_MTK(toAddress, valueMTK).send({from: fromAddress, gas: 3000000, value: valueETH);
底层构建的JSON-RPC结构:
{
jsonrpc: '2.0',
method: 'eth_sendTransaction',
params: [{
from: fromAddress,
to: contractAddr,
value: valueETH,
data: keccak256(Buffer.from('transferETH_MTK(address,uint256)')).slice(0, 10) + toAddress.toLowerCase().replace('0x', '').padStart(64, '0') + BigInt(valueMTK).toString(16).padStart(64, '0'),
gas: '0x300000'
}],
id: 1
}
from: fromAddress,
to: toAddress,
value: valueETH,给toAddress转valueETH个ETH,
data: funcName(toAddress, valueMTK)是合约方法和参数,调用transferETH_MTK(address,uint256),
fromAddress账户调用contractAddr合约中的transferETH_MTK方法, 给toAddress账户转valueMTK个MTK代币,同时给toAddress账户转valueETH个ETH以太币
const { ethers } = require("hardhat");
const { default: Web3 } = require('web3');
const fs = require('fs');
const path = require('path');
const { bigint } = require("hardhat/internal/core/params/argumentTypes");
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给合约账户转账ETH和MTK
async function web3js_contract_transaction(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);
// 查询发送者余额
var balance = await web3.eth.getBalance(fromAddress);
console.log("fromAddress 发送前ETH:", web3.utils.fromWei(balance, 'ether'));
// 查询接收者余额
var balance = await web3.eth.getBalance(contractAddress);
console.log("toAddress 接收前ETH:", web3.utils.fromWei(balance, 'ether'));
// 查询发送者余额
var balance = await contract.methods.balanceOf(fromAddress).call();
console.log("fromAddress 发送前MTK:", balance / BigInt(10 ** 18));
// 查询接收者余额
var balance = await contract.methods.balanceOf(contractAddress).call();
console.log("toAddress 发送前MTK:", balance / BigInt(10 ** 18));
// 调用合约中的transferETH_MTK方法,给toAddress转10个MTK和10个ETH
var receipt = await contract.methods.transferETH_MTK(toAddress, 10 * 10 ** 18).send({from: fromAddress, gas: 3000000, value: web3.utils.toWei('10', 'ether')});
// 查询发送者余额
var balance = await web3.eth.getBalance(fromAddress);
console.log("fromAddress 发送后ETH:", web3.utils.fromWei(balance, 'ether'));
// 查询接收者余额
var balance = await web3.eth.getBalance(contractAddress);
console.log("toAddress 接收后ETH:", web3.utils.fromWei(balance, 'ether'));
// 查询发送者余额
var balance = await contract.methods.balanceOf(fromAddress).call();
console.log("fromAddress 发送后MTK:", balance / BigInt(10 ** 18));
// 查询接收者余额
var balance = await contract.methods.balanceOf(contractAddress).call();
console.log("toAddress 发送后MTK:", balance / BigInt(10 ** 18));
}
async function main() {
var contractAddress = await deploy();
console.log("web3js 给合约账户转账ETH和MTK:");
await web3js_contract_transaction(contractAddress);
}
main().then();
读操作用call(),写操作用send()
web3.js内部将method赋值eth_call。合约地址放入to,方法名和参数放入data,赋值给params,组装jsonrpc。
读操作不消耗gas,从本地节点直接返回,不组装交易结构,不进行挖矿。所以不需要交易结构中的from、value、gaslimit、gasprice。
写操作消耗gas,广播到区块链上的节点,组装交易结构,进行挖矿。所以需要交易结构中的from、gaslimit、gasprice,默认不需要value。
2. 安装依赖
npm install web3
3. 启动Hardhat本地节点
npx hardhat node

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

hardhat node输出


1767

被折叠的 条评论
为什么被折叠?



