Web3 Development Skill
本技能专为 Web3 智能体任务平台开发而设计,涵盖区块链全栈开发最佳实践。
适用场景
- •智能合约开发(Solidity)
- •DApp 前端集成(wagmi、viem、RainbowKit)
- •钱包连接与交易签名
- •DeFi 协议集成(Aave、Uniswap 等)
- •DAO 治理与投票系统
- •多链部署与兼容
智能合约开发规范
目录结构
code
contracts/ ├── core/ # 核心业务合约 │ ├── TaskEscrow.sol # 任务托管 │ ├── AgentRegistry.sol # Agent 注册 │ └── DAOGovernance.sol # DAO 治理 ├── integrations/ # 第三方协议集成 │ └── AaveIntegration.sol # Aave 理财对接 ├── interfaces/ # 接口定义 ├── libraries/ # 工具库 └── test/ # 测试文件
安全最佳实践
- •
访问控制
- •使用 OpenZeppelin 的
Ownable、AccessControl - •关键函数添加
onlyOwner、onlyRole修饰符 - •多签钱包用于敏感操作
- •使用 OpenZeppelin 的
- •
重入攻击防护
- •使用
ReentrancyGuard - •遵循 Checks-Effects-Interactions 模式
solidity// ✅ 正确模式 function withdraw(uint amount) external nonReentrant { require(balances[msg.sender] >= amount); // Checks balances[msg.sender] -= amount; // Effects payable(msg.sender).transfer(amount); // Interactions } - •使用
- •
整数溢出
- •Solidity 0.8+ 自带溢出检查
- •复杂计算使用 OpenZeppelin
Math库
- •
权限分离
- •合约升级权限独立
- •资金管理权限独立
- •避免单点故障
代码规范
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title TaskEscrow
* @notice 任务资金托管合约,支持 ETH 和 ERC20 代币
* @dev 实现任务创建、承接、交付、结算的完整生命周期
*/
contract TaskEscrow is ReentrancyGuard, Ownable {
// 使用 uint256 而非 uint
// 常量使用 UPPER_SNAKE_CASE
uint256 public constant MIN_COMMISSION_RATE = 500; // 5%
uint256 public constant MAX_COMMISSION_RATE = 1000; // 10%
// 事件命名使用过去式
event TaskCreated(uint256 indexed taskId, address indexed employer);
event TaskCompleted(uint256 indexed taskId, address indexed agent);
// 错误使用 custom errors(省 gas)
error InsufficientFunds();
error TaskNotFound();
error Unauthorized();
}
前端 Web3 集成
技术栈
- •wagmi v2 - React Hooks for Ethereum
- •viem - 底层以太坊交互库
- •RainbowKit - 钱包连接 UI
- •TanStack Query - 数据缓存与状态管理
钱包连接配置
typescript
// config/wagmi.ts
import { getDefaultConfig } from "@rainbow-me/rainbowkit";
import { mainnet, sepolia, polygon, arbitrum } from "wagmi/chains";
export const config = getDefaultConfig({
appName: "Web3 Agent Marketplace",
projectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_ID!,
chains: [mainnet, sepolia, polygon, arbitrum],
ssr: false,
});
合约交互 Hook
typescript
// hooks/useTaskContract.ts
import {
useReadContract,
useWriteContract,
useWaitForTransactionReceipt,
} from "wagmi";
import { parseEther } from "viem";
export function useCreateTask() {
const { writeContract, data: hash, isPending, error } = useWriteContract();
const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({
hash,
});
const createTask = async (title: string, budget: string) => {
writeContract({
address: TASK_ESCROW_ADDRESS,
abi: TaskEscrowABI,
functionName: "createTask",
args: [title],
value: parseEther(budget),
});
};
return { createTask, isPending, isConfirming, isSuccess, error, hash };
}
交易状态管理
typescript
// 三态处理:等待签名 → 确认中 → 完成/失败
const TransactionButton = ({ onSubmit }) => {
const { isPending, isConfirming, isSuccess, error, hash } = useTransaction();
if (isPending) return <Button disabled>等待钱包签名...</Button>;
if (isConfirming) return <Button disabled>交易确认中...</Button>;
if (isSuccess) return <Success txHash={hash} />;
if (error) return <ErrorMessage error={error} />;
return <Button onClick={onSubmit}>提交交易</Button>;
};
Aave 协议集成
核心接口
typescript
// Aave V3 Pool 接口
interface IAavePool {
supply(
asset: address,
amount: uint256,
onBehalfOf: address,
referralCode: uint16
): void;
withdraw(asset: address, amount: uint256, to: address): uint256;
borrow(
asset: address,
amount: uint256,
interestRateMode: uint256,
referralCode: uint16,
onBehalfOf: address
): void;
repay(
asset: address,
amount: uint256,
interestRateMode: uint256,
onBehalfOf: address
): uint256;
}
收益查询
typescript
// hooks/useAavePosition.ts
export function useAavePosition(userAddress: string) {
const { data: position } = useReadContract({
address: AAVE_POOL_ADDRESS,
abi: AavePoolABI,
functionName: "getUserAccountData",
args: [userAddress],
});
return {
totalCollateral: position?.[0],
totalDebt: position?.[1],
availableBorrows: position?.[2],
healthFactor: position?.[5],
};
}
DAO 治理
提案结构
solidity
struct Proposal {
uint256 id;
address proposer;
string description;
uint256 forVotes;
uint256 againstVotes;
uint256 startBlock;
uint256 endBlock;
bool executed;
ProposalType proposalType; // protocol | treasury | arbitration | fee
}
投票权计算
- •基于 ERC20 代币持有量
- •支持委托投票
- •快照机制防止双花
测试规范
合约测试(Foundry)
solidity
// test/TaskEscrow.t.sol
contract TaskEscrowTest is Test {
TaskEscrow escrow;
address employer = makeAddr("employer");
address agent = makeAddr("agent");
function setUp() public {
escrow = new TaskEscrow();
vm.deal(employer, 10 ether);
}
function test_CreateTask() public {
vm.prank(employer);
uint256 taskId = escrow.createTask{value: 1 ether}("Test Task");
assertEq(escrow.getTaskBudget(taskId), 1 ether);
}
function testFuzz_CreateTaskWithVariousBudgets(uint256 budget) public {
vm.assume(budget > 0.01 ether && budget < 100 ether);
vm.prank(employer);
escrow.createTask{value: budget}("Fuzz Task");
}
}
前端测试
typescript
// __tests__/useTaskContract.test.ts
import { renderHook, waitFor } from "@testing-library/react";
import { useCreateTask } from "../hooks/useTaskContract";
describe("useCreateTask", () => {
it("should create task with correct parameters", async () => {
const { result } = renderHook(() => useCreateTask());
await result.current.createTask("Test Task", "1.0");
await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
});
});
});
部署检查清单
- • 合约代码通过 Slither 静态分析
- • 单元测试覆盖率 > 80%
- • Gas 优化(storage 访问、循环优化)
- • 事件日志完整
- • 升级路径明确(代理模式)
- • 紧急暂停机制
- • 多签钱包配置
- • 测试网充分验证
常见问题
Q: 如何处理交易失败?
A: 使用 try-catch 捕获错误,解析错误信息,向用户展示友好提示。
Q: 如何优化 Gas 费用?
A: 批量操作、存储打包、使用 calldata、避免循环中的 storage 访问。
Q: 如何保证数据一致性?
A: 使用事件索引 + The Graph 查询,实现链上链下数据同步。