使用hardhat + ganache进行本地solidity开发
hardhat是有本地开发网络的,但ganache是个有界面的程序,也是在本地模拟一个以太坊链,但是界面比较漂亮一些。
hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.19",
networks: {
ganache: {
url: "http://127.0.0.1:7545",
accounts: ["0x624cfb2cb9b9c3212abfa2800fd8de8e2501c84500336007f4459c50198c69f7"]
}
}
};
如上,本地装好ganache并启动以后,我们在里边找一个账户对应的私钥0x624cfb2cb9b9c3212abfa2800fd8de8e2501c84500336007f4459c50198c69f7,把他配置到hardhat.config.js里,ganache的rpc地址默认是http://127.0.0.1:7545,以上我们命名一个名叫ganache
的网络。
这样我们就可以部署并测试合约了,例如:npx hardhat run scripts/testcall.js --network ganache
以及: npx hardhat run scripts/deploy.js --network ganache
合约的编写、测试、部署,参照hardhat官方的tuitorial的Token合约:https://hardhat.org/tutorial
这里再补充一个合约部署好以后如何对方法进行调用测试的例子:
scripts/testcall.js
const { ethers } = require("hardhat");
const contractABI = [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "_from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "_value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
];
async function main(){
const contractAddress = "0xFb9f331194eE63630f3d2A7B76Aa1f9C94D18878";
const provider = ethers.getDefaultProvider("http://localhost:7545/");
//获取地址有多少ETH,获取当前区块高度
const queryAddress = "0xF7A1938Fecc594aaF126d46fd173cE74A659ad9A";
let ethBalance = await provider.getBalance(queryAddress);
console.log("地址%s有%s个ETH", queryAddress, ethBalance);
let blockNumber = await provider.getBlockNumber();
console.log("当前链上区块高度%s", blockNumber);
//调用合约方法
//查询(调用合约的balanceOf方法)
let tokenContract = await new ethers.Contract(contractAddress, contractABI, provider);
let tokenBalance = await tokenContract.balanceOf(queryAddress);
console.log("地址%s有%s个Token", queryAddress, tokenBalance);
tokenBalance = await tokenContract.balanceOf("0x72BbA0fE9D0dA19b27705BCdDAb783BeED24bbDb");
console.log("地址%s有%s个Token", "0x72BbA0fE9D0dA19b27705BCdDAb783BeED24bbDb", tokenBalance);
//写(调用合约的transfer方法)
let signer = await new ethers.Wallet("0x624cfb2cb9b9c3212abfa2800fd8de8e2501c84500336007f4459c50198c69f7", provider);
let tokenContractConnected = await tokenContract.connect(signer);
let txn = await tokenContractConnected.transfer("0x72BbA0fE9D0dA19b27705BCdDAb783BeED24bbDb", 100);
//再次查询
tokenBalance = await tokenContract.balanceOf(queryAddress);
console.log("地址%s有%s个Token", queryAddress, tokenBalance);
tokenBalance = await tokenContract.balanceOf("0x72BbA0fE9D0dA19b27705BCdDAb783BeED24bbDb");
console.log("地址%s有%s个Token", "0x72BbA0fE9D0dA19b27705BCdDAb783BeED24bbDb", tokenBalance);
}
main()
.then(() => {
process.exit(0);
})
.catch((error) => {
console.error(error);
process.exit(1);
});