核心关键词:闪电贷套利、Aave 协议、Hardhat 开发、DeFi 量化、智能合约部署、测试网操作、无抵押借贷
在去中心化金融(DeFi)的世界里,闪电贷套利是一种“用代码印钞”的典型玩法:无需本金,仅凭代码逻辑+时序优势即可锁定价差收益。本文将以 Aave V3 的闪电贷功能为主线,手把手教你用 Hardhat 完成从环境搭建到盈利回测的全过程,确保每一步都可本地复现、可测可信。
一、前置条件速查
开始前,请先确认已具备以下软硬条件:
- 区块链基础:理解区块、Gas、事务生命周期
- Solidity 语言:变量、事件、修饰器、接口用法
- Hardhat 使用经验:编译、测试、部署、Fork 主网
- 工具链:Node.js ≥16、npm 或 yarn、Git
二、闪电贷套利原理 30 秒扫盲
- 发现价差
在两家 DEX 中发现同一代币存在 2% 以上价差。 - 闪电贷
向 Aave 贷款 10,000 USDC(无抵押,零风险敞口)。 - 套利
使用 10,000 USDC 低价买 DAI,再在高价处卖出,瞬间锁定利润。 - 还款
同一事务内归还 10,000 + 0.05% 手续费,剩余收益进入钱包。
👉 想知道如何最小化滑点?这里有技巧
三、项目初始化与依赖安装
Step 1 创建 Hardhat 项目
mkdir aave-flash-arbitrage && cd aave-flash-arbitrage
npm install --save-dev hardhat
npx hardhat终端中选择 JavaScript 模板,其余默认即可。
Step 2 安装核心库
yarn add --dev \
hardhat-deploy hardhat-deploy-ethers \
hardhat-gas-reporter prettier solhint \
solidity-coverage dotenv
yarn add @aave/core-v3四、项目结构规划
aave-flash-arbitrage
├── contracts/
│ ├── FlashLoanArbitrage.sol
│ └── Dex.sol
├── deploy/
│ ├── 00-deployDex.js
│ └── 01-deployFlashLoanArbitrage.js
├── scripts/
├── test/
├── .env
├── hardhat.config.js
├── helper-hardhat-config.js
└── README.md五、配置开发网络与密钥
在根目录新建 .env:
SEPOLIA_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/<你的 API key>
PRIVATE_KEY=<0x 64 位十六进制私钥>hardhat.config.js 加入 Sepolia 测试网配置:
require("@nomiclabs/hardhat-waffle");
require("hardhat-deploy");
require("dotenv").config();
module.exports = {
defaultNetwork: "hardhat",
networks: {
hardhat: { chainId: 31337 },
sepolia: {
url: process.env.SEPOLIA_RPC_URL,
accounts: [process.env.PRIVATE_KEY],
chainId: 11155111,
saveDeployments: true
}
},
namedAccounts: { deployer: 0, player: 1 },
solidity: { compilers: [{ version: "0.8.10" }] },
mocha: { timeout: 500000 }
};helper-hardhat-config.js 放公共参数,方便测试网和主网切换:
const networkConfig = {
11155111: {
name: "sepolia",
PoolAddressesProvider: "0x0496275d34753A48320CA58103d5220d394FF77F",
daiAddress: "0x68194a729C2450ad26072b3D33ADaCbcef39D574",
usdcAddress: "0xda9d4f9b69ac6C22e444eD9aF0CfC043b7a7f53f"
}
};
module.exports = { networkConfig };六、智能合约解析
1. Dex.sol:制造套利场景
该合约人为设置两种代币汇率,两边不平衡时便会出现套利窗口。
pragma solidity 0.8.10;
import {IERC20} from "@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol";
contract Dex {
address payable public owner;
IERC20 private dai;
IERC20 private usdc;
uint256 public dexARate = 90; // 100 单位 USDC 可买 111 单位 DAI
uint256 public dexBRate = 100; // 111 单位 DAI 可换回 111 单位 USDC
constructor(address _dai, address _usdc) {
owner = payable(msg.sender);
dai = IERC20(_dai);
usdc = IERC20(_usdc);
}
function depositUSDC(uint256 _amount) external { /*...*/ }
function buyDAI() external { /*...*/ }
function sellDAI() external { /*...*/ }
}要点:
dexARate ≠ dexBRate即价差来源- 为防止滑点过大,我们在同一事务里完成 AAVE→套利→还款 的全闭环
2. FlashLoanArbitrage.sol:核心逻辑
executeOperation 是闪电贷成功的回调函数,由此插入价差逻辑即可。
pragma solidity 0.8.10;
import {FlashLoanSimpleReceiverBase} from "@aave/core-v3/contracts/flashloan/base/FlashLoanSimpleReceiverBase.sol";
interface IDex {
function depositUSDC(uint256 _amount) external;
function buyDAI() external;
function depositDAI(uint256 _amount) external;
function sellDAI() external;
}
contract FlashLoanArbitrage is FlashLoanSimpleReceiverBase {
IERC20 private dai;
IERC20 private usdc;
IDex private dex;
constructor(address _provider, address _dai, address _usdc)
FlashLoanSimpleReceiverBase(IPoolAddressesProvider(_provider))
{
dai = IERC20(_dai);
usdc = IERC20(_usdc);
}
function executeOperation(
address asset,
uint256 amount,
uint256 premium,
address,
bytes calldata
) external override returns (bool) {
// 1. 把 USDC 充值到 Dex
usdc.approve(address(dex), amount);
dex.depositUSDC(amount);
// 2. 低价买入 DAI
dex.buyDAI();
// 3. 卖出 DAI 获利更多 USDC
dai.approve(address(dex), dai.balanceOf(address(this)));
dex.depositDAI(dai.balanceOf(address(this)));
dex.sellDAI();
// 4. 计算并归还本息
uint256 amountOwed = amount + premium;
usdc.approve(address(POOL), amountOwed);
return true;
}
function requestFlashLoan(address _token, uint256 _amount) external {
POOL.flashLoanSimple(address(this), _token, _amount, "", 0);
}
}七、部署脚本
deploy/00-deployDex.js
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy, log } = deployments;
const { deployer } = await getNamedAccounts();
const { daiAddress, usdcAddress } = network.config;
const dex = await deploy("Dex", {
from: deployer,
args: [daiAddress, usdcAddress],
log: true
});
log("Dex deployed at:", dex.address);
};
module.exports.tags = ["dex"];deploy/01-deployFlashLoanArbitrage.js
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy, log } = deployments;
const { deployer } = await getNamedAccounts();
const { PoolAddressesProvider, daiAddress, usdcAddress } = network.config;
const flash = await deploy("FlashLoanArbitrage", {
from: deployer,
args: [PoolAddressesProvider, daiAddress, usdcAddress],
log: true
});
log("FlashLoanArbitrage deployed at:", flash.address);
};
module.exports.tags = ["flash"];部署到 Sepolia 测试网:
yarn hardhat deploy --tags dex --network sepolia
yarn hardhat deploy --tags flash --network sepolia八、Remix + Etherscan 复测流程
- 资金预热
向 Dex 分别打入 1,500 USDC 与 1,500 DAI 作为流动性池。 触发套利
Loader 页面调用requestFlashLoan,参数:token: 0xda9d4f9b69ac6C22e444eD9aF0CfC043b7a7f53f amount: 1000000000 (1000 USDC)查看结果
交易完成后可链上验证步骤:- 借入 1000 USDC
- 合约盈利约 110.6 USDC
- 共归还 1000.5 USDC(手续费 0.05)
九、纵览收益模型
| 场景 | 价差 | 投入本金 | 单笔盈利 (扣手续费) |
|---|---|---|---|
| ETH/USDC | 2% | 0 USD | 19.95 USDC |
| DAI/USDC | 3% | 0 USD | 29.85 USDC |
FAQ:闪电贷套利常见疑问
Q1:闪电贷真的零风险吗?
A:在同一事件内还清借款即可保证无清算风险。唯一成本是 0.05–0.09% 手续费。
Q2:手续费太高会不会吃掉套利利润?
A:需确保价差 ≥0.1%。多数场景配合聚合器或滑点控制可做到 ≥0.2% 无虞。
Q3:能否在真实主网部署?
A:行,但务必先 fork 主网跑 net profit simulation,确认 Gas 与价格时效。
Q4:如何避免闪电贷多次调用导致的重入?
A:executeOperation 内使用互斥锁或在返回值中检查所有资金路径,确保 ether transfer last。
Q5:账户没有钱怎么部署测试?
A:使用 Sepolia 或 Goerli 测试网,DApp 工具自带的龙头可领取 DAI/USDC 无需充值。
Q6:如果同一套利逻辑被抢先怎么办?
A:引入 MEV 专属 RPC(如 Flashbots),或使用区间时间锁策略,减少抢跑机器人干扰。
十、结语与拓展
本文以最小可行样本演示了Aave 闪电贷套利全流程:从编码、测试、部署,到链上校验利润。真正的量化策略远比这复杂——需实时获取全市场汇率、动态算路、控制滑点与 Gas。你已迈出第一步,接下来:
- 接入 Off-chain 数据预言机 提升价差侦测精度
- 把
Dex.sol替换为 Uniswap V3 + Curve 组合 - 使用 Hardhat node 仿真 自动回归测试(10s/次)
祝你在下一轮链上波动前先人一步。代码即资产,能力即自由!