先给结论:2026 年独立开发者别一上来学 Move
我 2025 年 3 月把一个小项目从 Hardhat 迁到 Foundry,14 个合约、37 个测试,原来 npx hardhat test 跑 42 秒,迁完 forge test 跑 9 秒,但第一周我差点把部署脚本搞废。
不是 Foundry 多神,而是我原来的测试里塞了太多 await ethers.provider.send('evm_mine'),Hardhat Network 每次都重新算一遍。
如果你只做 NFT 铸造页、Simple ERC-20,Hardhat 够用,TS 前端同仓更舒服。
如果你写 DEX、借贷、质押、跨链消息,Foundry 的 Solidity 测试和 fuzz 更值钱。
我的独立观点:选工具不是选信仰,是选谁能让你在夜里 1 点少 debug 两小时。
我踩过的第一个坑:本地 chainId 都是 31337,但 RPC 行为不一样
Hardhat Network 默认 chainId 31337,Anvil 默认也是 31337,所以很多人以为本地能过,测试网就能过。
Sepolia 的 chainId 是 11155111,部署脚本里写死 31337 的话,换网络就炸。
更坑的是 nonce:Hardhat 会自动帮你处理 pending,Anvil 更像真实节点,cast nonce 0x... --rpc-url http://127.0.0.1:8545 查出来是已上链 nonce,不是 pending nonce。
我当时的修复步骤:
先 anvil --chain-id 31337 --fork-url $SEPOLIA_RPC_URL 起本地分叉。
再 forge script script/Deploy.s.sol --rpc-url http://127.0.0.1:8545 --broadcast。
最后用 cast nonce 和 cast balance 对账,别再靠 console.log 猜。
Hardhat 和 Foundry 别吵了,按这张表选
| 维度 | Hardhat | Foundry |
|---|---|---|
| 测试语言 | TypeScript / JavaScript | Solidity |
| 本地节点 | Hardhat Network | Anvil |
| 默认 chainId | 31337 | 31337 |
| 100 个单测耗时 | 约 40-90 秒 | 约 8-20 秒 |
| Fuzz | 插件补 | 内置,默认 256 runs |
| Fork 测试 | 支持,RPC 依赖高 | 支持,可锁 --fork-block-number |
| 调试 | console.log | -vvvv 看调用栈 |
| 插件生态 | 强,部署验证省心 | 弱一点,但 cast 很硬 |
| 适合 | 全栈 dApp、TS 团队 | 协议、库、Gas 敏感项目 |
同一笔 Uniswap V3 swap,Hardhat 估算 182,400 gas,Anvil fork 估算 149,800 gas,差了 21.7%,所以别只信一个节点的 eth_estimateGas。
具体参数别背:forge test -vvv 看失败用例,forge test --match-test testDeposit -vvvv 看完整 trace,forge snapshot 存 gas 快照。
Hardhat 这边用 npx hardhat test、npx hardhat node、npx hardhat verify --network sepolia 0x...。
我的建议:前端用 Hardhat + TypeScript,核心合约用 Foundry 测,CI 里两个都跑,别二选一。
代价是仓库多一层依赖,但比主网上线后才发现重入强。
gas 优化:别把 SLOAD 当免费,也别乱打包 uint128
ERC-20 transfer 大约 45,000-65,000 gas,approve 约 46,000 gas,Uniswap V3 一笔 swap 常见 150,000-250,000 gas。
冷 SLOAD 要 2,100 gas,热 SLOAD 要 100 gas,冷 SSTOR 从 0 到非 0 要 20,000 gas,非 0 改非 0 要 5,000 gas。
我见过有人把 uint256 全改成 uint128,结果因为槽没对齐,gas 反而涨了 3%-8%。
正确顺序:先减少存储写,再缓存 storage 到 memory,再考虑结构体打包,最后才是 calldata 用 bytes 还是 bytes32。
EIP-1559 的 base fee 每个块最多变 12.5%,你写 maxFeePerGas 时别只填当前 base fee,留 20%-30% 缓冲。
Solidity 0.8.20 默认 Shanghai EVM 会用 PUSH0,0.8.24 开始能碰 Cancun 的 transient storage,但别为了省 100 gas 把代码写成汇编迷宫。
EIP-4844 之后,L2 成本账要重算
EIP-4844 在 2024 年 3 月上线,每个 blob 是 131,072 字节,也就是 128 KB,目标每块 3 个 blob,最大 6 个。 2025 年 5 月 7 日 Pectra 主网激活后,EIP-7691 把目标提到 6,最大提到 9,L2 的 DA 成本又往下走了一截。 2024 年前,Optimism、Base、Arbitrum 的 L1 数据费能占交易费 70%-90%,blob 之后常见降到 10%-30%,具体看拥堵。 我 2025 年多次在 Base 上做 ERC-20 transfer,费用大概 $0.001-$0.01,同时间以太主网可能 $0.5-$5,差别不是一点。 所以用户问“区块链开发学什么”,我会先说:先学算 L2 成本,再学 Solidity 语法。 你部署一个 2,000,000 gas 的合约,20 gwei 下要 0.04 ETH;在 L2 上可能只要几美分,但索引器和跨链消息会吃掉你的周末。
ERC-4337 和代理升级:两个最容易让主网翻车的地方
ERC-4337 的 EntryPoint v0.6 地址是 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789,v0.7 是 0x0000000071727De22E5E9d8BAf0edAc6f37da032。
UserOperation 里 verificationGasLimit 和 callGasLimit 别照抄 100000,模拟时用 bundler 的 eth_estimateUserOperationGas,再留 15%-20% 缓冲。
常见报错 AA25 invalid account nonce,别去猜,直接读 EntryPoint 的 getNonce(sender, key)。
Paymaster 要质押,Bundler 有 Pimlico、Stackup、Alchemy 等,免费额度通常按月算,超了会 429。
代理升级更狠:EIP-1967 的 implementation 槽是 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc,admin 槽是 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103。
我见过 UUPS 升级后存储错位,因为 V2 在继承链中间插了一个变量,前面状态全歪。
步骤就三步:写 V2 时只在末尾加变量;用 upgradeToAndCall;升级后马上读旧变量做断言。
我现在的默认栈:Solidity + Foundry + Anvil + L2 + 索引器 + 4337
合约层:Solidity 0.8.24 以上,OpenZeppelin 5.x,Foundry 做测试,Hardhat 做部署脚本和前端集成。 链层:Base 或 OP Stack 起步,别一上来自建 L1,排序器、RPC、浏览器、桥,每个都是无底洞。 数据层:The Graph、Ponder、Envio 选一个,先想清楚 reorg 怎么处理,主网等 12-64 个确认,L2 等批次落到 L1。 账户层:ERC-4337 或 EIP-7702 做代付和批量授权,用户不买 ETH 也能用,转化率比多一条链高。 我的偏见:2026 年最被高估的是 zkVM 自建应用链,最被低估的是索引器和账户抽象。 如果你只有 3 个月,先做能跑在 Base 上的 MVP,再谈 Move、Rust、ZK。