9. web3.js给合约账户同时转以太币和代币

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个ETHdata: 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输出
在这里插入图片描述

一. 系列视频
二. 系列文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OneFlyPig

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值