1. 构建本地测试网络
bash
// 在命令行中执行
anvil
获取到本地RPC URL
地址127.0.0.1:8545
如图下结果所示,则表示本地测试网络已经启动:
2.forge 构建项目写个 HelloWorld 合约
solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract HelloWorld {
string public showMsg='hello world';
function showSomeMsg() public view returns(string memory){
return showMsg;
}
function getMsg(string calldata newMsg) public pure returns(string calldata){
return newMsg;
}
}
写了两个函数,view
与pure
都是不用花费 gas。
3.编译合约,获取到对应的 ABI 文件
bash
forge build
在项目根目录下找到 out
,把 HelloWorld.json
文件拷贝到前端项目目录下(也可放线上等待前端来请求)。
4.部署合约到本地测试网络
先取本地没测试帐号的地址,我取了第一个0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
,如果是 windows 系统,配置一下环境变量,ETH_FROM=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
,再好下配置 foundry.toml 文件,配置如下:
toml
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
rpc_url = "anvil"
private_key = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
[rpc_endpoints]
anvil = "http://127.0.0.1:8545"
// 上面的私钥也是取的第一个帐户对应的私钥
所有配置完成后,执行以下命令,部署合约到本地测试网络:
bash
forge create --unlocked src\HelloWorld.sol:HelloWorld
执行成功后,会返回合约地址,如下所示:
bash
Deployer: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
Deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3
Transaction hash: 0x2679c0995453ab9b31eb49477704a5ee7dab2c183db0ce8d476e04375d4704a9
上面的值在前端中要用到。
5.构建一个 React 前端项目
在前端与合约交互,需要用到 ethers.js 库,按如下配置:
ts
import { ethers } from 'ethers'
// 合约 ABI
import HelloWorldContractABI from '../../public/ABI/HelloWorld.json' assert { type: 'json' }
// 合约部署地址
const contractAddress = '0x5FbDB2315678afecb367f032d93F642f64180aa3'
// 本地测试网络 RPC 地址
const rpcUrl = 'http://127.0.0.1:8545'
async function getContract() {
const provider = new ethers.JsonRpcProvider(rpcUrl)
const contract = new ethers.Contract(
contractAddress,
HelloWorldContractABI.abi,
provider,
)
return contract
}
const contract = await getContract()
export { contract }
6.前端调用合约的两个函数
前端代码如下:
import { useState } from 'react'
import './App.css'
import { contract } from './utils/contract'
function App() {
const [pure, setPure] = useState('')
const [view, setView] = useState('')
const pureFunc = async () => {
const res = await contract.getMsg('我是React')
setPure(res)
}
const viewFunc = async () => {
const res = await contract.showSomeMsg()
setView(res)
}
return (
<>
<div className="card">
<button onClick={pureFunc}>调用合约pure函数</button>
<p>合约调用返回值:{pure}</p>
</div>
<div className="card">
<button onClick={viewFunc}>调用合约view函数</button>
<p>合约调用返回值:{view}</p>
</div>
</>
)
}
调用成功后,页面显示如下: