Files
interview/questions/14-Web3与区块链/DeFi协议与AMM.md

1071 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DeFi协议与AMM
## 问题
1. 什么是DeFi去中心化金融与传统金融的区别
2. 什么是AMM自动做市商它如何工作
3. Uniswap V2、V3的区别是什么
4. 什么是流动性池Liquidity Pool
5. 什么是无常损失Impermanent Loss如何计算
6. 什么是流动性挖矿Yield Farming
7. 什么是闪电贷Flash Loan有什么应用场景
8. 什么是DEX聚合器1inch如何工作
9. 借贷协议Aave、Compound如何工作
10. 什么是清算Liquidation如何避免被清算
---
## 标准答案
### 1. DeFi vs 传统金融
#### **对比表**
| 特性 | 传统金融CeFi | 去中心化金融DeFi |
|------|-----------------|---------------------|
| **中介** | 银行、券商 | 智能合约 |
| **准入门槛** | 需要KYC、银行账户 | 只需要钱包 |
| **营业时间** | 工作日 9-5 | 24/7 |
| **透明度** | 不透明 | 完全透明 |
| **速度** | 1-3天 | 几秒到几分钟 |
| **成本** | 高(中介费) | 低Gas费 |
| **风险** | 信用风险、操作风险 | 智能合约风险、黑客攻击 |
#### **DeFi核心组件**
```
1. 交易所DEX
- UniswapAMM
- Curve稳定币
- Balancer
2. 借贷
- Aave
- Compound
- MakerDAO
3. 稳定币
- USDT、USDC中心化
- DAI去中心化
4. 衍生品
- dYdX
- Synthetix
- GMX
5. 聚合器
- 1inch
- Paraswap
```
---
### 2. AMM自动做市商
#### **传统订单簿 vs AMM**
**传统订单簿CEX**
```
买单Bid 卖单Ask
100 USDT @ 2000 101 USDT @ 2001
150 USDT @ 1999 200 USDT @ 2002
200 USDT @ 1998 150 USDT @ 2003
需要:
- 买卖双方
- 撮合引擎
- 做市商提供流动性
```
**AMMDEX**
```
流动性池:
- ETH/USDT 池
- 100 ETH + 200,000 USDT
- 价格 = 2000 USDT/ETH
不需要:
- 买卖双方匹配
- 撮合引擎
- 传统做市商
由算法自动定价
```
---
#### **Uniswap V2恒定乘积公式**
```
x * y = k
x = Token A 的数量
y = Token B 的数量
k = 恒定值(常数)
```
**示例**
```solidity
// Uniswap V2 核心公式
function getAmountOut(
uint amountIn,
uint reserveIn,
uint reserveOut
) public pure returns (uint amountOut) {
uint amountInWithFee = amountIn * 997; // 0.3% 手续费
uint numerator = amountInWithFee * reserveOut;
uint denominator = reserveIn * 1000 + amountInWithFee;
amountOut = numerator / denominator;
}
```
**交易示例**
```
初始状态:
ETH Reserve: 100 ETH
USDT Reserve: 200,000 USDT
k = 100 * 200,000 = 20,000,000
用户用 1 ETH 买 USDT
1. 输入1 ETH
2. 手续费1 * 0.3% = 0.003 ETH
3. 实际参与定价0.997 ETH
4. 新的 ETH 储备100 + 0.997 = 100.997 ETH
5. 新的 USDT 储备20,000,000 / 100.997 ≈ 198,025.94 USDT
6. 用户获得200,000 - 198,025.94 ≈ 1,974.06 USDT
价格影响:
- 实际价格1,974.06 USDT/ETH
- 理论价格2,000 USDT/ETH
- 滑点:(2000 - 1974.06) / 2000 ≈ 1.3%
```
---
#### **价格滑点Slippage**
```
交易量越大,价格滑点越大
公式:
新价格 = (reserveOut * amountIn) / (reserveIn + amountIn)
滑点 = (原价格 - 新价格) / 原价格
```
**代码示例**
```go
type AMM struct {
ReserveTokenA float64
ReserveTokenB float64
Fee float64 // 0.003 = 0.3%
}
func (a *AMM) Swap(amountIn float64, tokenIn string) float64 {
if tokenIn == "A" {
amountInWithFee := amountIn * (1 - a.Fee)
amountOut := (a.ReserveTokenB * amountInWithFee) / (a.ReserveTokenA + amountInWithFee)
// 更新储备
a.ReserveTokenA += amountIn
a.ReserveTokenB -= amountOut
return amountOut
}
// 反向交易类似
return 0
}
func (a *AMM) GetPrice() float64 {
return a.ReserveTokenB / a.ReserveTokenA
}
func (a *AMM) GetSlippage(amountIn float64) float64 {
spotPrice := a.GetPrice()
amountOut := a.Swap(amountIn, "A")
executionPrice := amountIn / amountOut
return (executionPrice - spotPrice) / spotPrice
}
```
---
### 3. Uniswap V3集中流动性
#### **V2 vs V3 对比**
| 特性 | Uniswap V2 | Uniswap V3 |
|------|-----------|-----------|
| **流动性范围** | 0 ~ ∞(全范围) | 自定义价格区间 |
| **资金效率** | 低 | 高最高4000倍 |
| **手续费** | 固定0.3% | 0.01%/0.05%/0.3%/1% |
| **LP Token** | ERC-20可替换 | NFT不可替换 |
| **适用场景** | 通用 | 稳定币、高波动币 |
---
#### **V3核心创新集中流动性**
**V2全范围流动性**
```
ETH价格2000 USDT
LP提供流动性
- 范围0 ~ ∞
- 实际交易区间1800 ~ 2200 USDT
- 资金利用率:(2200-1800) / ∞ ≈ 0%
大部分资金永远不会被使用
```
**V3集中流动性**
```
LP可以选择价格区间
- 下限1800 USDT
- 上限2200 USDT
- 当前价格2000 USDT
资金集中在这个区间,利用率大幅提高
```
**数学公式**
```solidity
// V3 流动性计算
function getLiquidityForAmounts(
uint160 sqrtRatioX96, // 当前价格的平方根
uint160 sqrtRatioAX96, // 价格区间下限的平方根
uint160 sqrtRatioBX96, // 价格区间上限的平方根
uint256 amount0,
uint256 amount1
) internal pure returns (uint128 liquidity) {
if (sqrtRatioAX96 > sqrtRatioBX96) {
(sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
}
if (sqrtRatioX96 <= sqrtRatioAX96) {
// 当前价格低于区间
liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);
} else if (sqrtRatioX96 < sqrtRatioBX96) {
// 当前价格在区间内
uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);
uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);
liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;
} else {
// 当前价格高于区间
liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);
}
}
```
---
#### **V3实际应用**
**稳定币池USDC/USDT**
```
价格区间0.999 ~ 1.001
手续费0.01%
资金效率V2的2000倍
原因:
- 稳定币价格几乎1:1
- 集中在极小区间
- 极高资金利用率
```
**高波动币ETH/SHIB**
```
价格区间0.00000001 ~ 0.0000001
手续费1%
资金效率V2的100倍
原因:
- 波动大,需要更宽区间
- 高风险,高手续费
```
---
### 4. 流动性池Liquidity Pool
#### **工作原理**
```
1. 流动性提供者LP存入两种代币
- 例如10 ETH + 20,000 USDT
2. 获得LP Token
- 代表池子份额
- 例如100 LP Token
3. 交易者交易
- 支付手续费0.3%
- 手续费留在池中
4. LP提取
- 返还LP Token
- 获得本金 + 手续费收益
```
#### **代码实现**
```solidity
pragma solidity ^0.8.0;
contract LiquidityPool {
uint256 public reserve0; // Token0 储备
uint256 public reserve1; // Token1 储备
uint256 public totalSupply; // LP Token 总量
mapping(address => uint256) public balanceOf; // LP Token 余额
// 添加流动性
function addLiquidity(
uint256 amount0,
uint256 amount1
) external returns (uint256 liquidity) {
// 转入代币
IERC20(token0).transferFrom(msg.sender, address(this), amount0);
IERC20(token1).transferFrom(msg.sender, address(this), amount1);
// 计算LP Token数量
if (totalSupply == 0) {
// 首次添加
liquidity = sqrt(amount0 * amount1);
} else {
liquidity = min(
(amount0 * totalSupply) / reserve0,
(amount1 * totalSupply) / reserve1
);
}
// 铸造LP Token
balanceOf[msg.sender] += liquidity;
totalSupply += liquidity;
// 更新储备
reserve0 += amount0;
reserve1 += amount1;
}
// 移除流动性
function removeLiquidity(
uint256 liquidity
) external returns (uint256 amount0, uint256 amount1) {
// 计算可提取数量
amount0 = (liquidity * reserve0) / totalSupply;
amount1 = (liquidity * reserve1) / totalSupply;
// 销毁LP Token
balanceOf[msg.sender] -= liquidity;
totalSupply -= liquidity;
// 更新储备
reserve0 -= amount0;
reserve1 -= amount1;
// 转出代币
IERC20(token0).transfer(msg.sender, amount0);
IERC20(token1).transfer(msg.sender, amount1);
}
}
```
---
### 5. 无常损失Impermanent Loss
#### **定义**
无常损失是指LP提供流动性后因价格变化导致的损失相对于单纯持有代币
#### **计算公式**
```
无常损失 = (池中资产价值 - 单纯持有价值) / 单纯持有价值
简化公式:
IL = 2 * sqrt(price_ratio) / (1 + price_ratio) - 1
price_ratio = 新价格 / 初始价格
```
#### **示例**
```
初始状态:
- ETH价格2000 USDT
- 存入1 ETH + 2000 USDT
- 总价值4000 USDT
价格上涨到 3000 USDT
1. 池子调整(套利者搬砖):
- 新储备0.816 ETH + 2449 USDT
- 池中价值0.816 * 3000 + 2449 = 4897 USDT
2. 单纯持有:
- 1 ETH + 2000 USDT
- 价值1 * 3000 + 2000 = 5000 USDT
3. 无常损失:
IL = (4897 - 5000) / 5000 = -2.06%
损失103 USDT
```
#### **代码计算**
```go
package main
import (
"fmt"
"math"
)
// 计算无常损失
func CalculateImpermanentLoss(priceRatio float64) float64 {
// IL = 2 * sqrt(r) / (1 + r) - 1
sqrtR := math.Sqrt(priceRatio)
il := (2*sqrtR)/(1+priceRatio) - 1
return il
}
// 计算LP收益考虑手续费
func CalculateLPReturn(
initialPrice float64,
finalPrice float64,
feeRate float64,
volume float64,
) float64 {
priceRatio := finalPrice / initialPrice
// 无常损失
il := CalculateImpermanentLoss(priceRatio)
// 手续费收益(假设交易量)
feeReturn := volume * feeRate
// 总收益 = 手续费收益 + 无常损失
totalReturn := feeReturn + il
return totalReturn
}
func main() {
// 价格从 2000 涨到 3000价格比率 1.5
il := CalculateImpermanentLoss(1.5)
fmt.Printf("无常损失: %.2f%%\n", il*100)
// 价格从 2000 跌到 1000价格比率 0.5
il2 := CalculateImpermanentLoss(0.5)
fmt.Printf("无常损失: %.2f%%\n", il2*100)
// 考虑手续费
totalReturn := CalculateLPReturn(2000, 3000, 0.003, 1000000)
fmt.Printf("总收益(含手续费): %.2f%%\n", totalReturn*100)
}
```
**输出**
```
无常损失: -2.06%
无常损失: -2.06%
总收益(含手续费): 1.94%
```
#### **无常损失表**
| 价格变化 | 无常损失 |
|---------|---------|
| 1.25x | -0.6% |
| 1.50x | -2.0% |
| 1.75x | -3.8% |
| 2.00x | -5.7% |
| 3.00x | -13.4% |
| 4.00x | -20.0% |
| 5.00x | -25.5% |
**结论**
- 价格变化越大,无常损失越大
- 稳定币池无常损失最小
- 高波动币池需要高手续费补偿
---
### 6. 流动性挖矿Yield Farming
#### **定义**
通过提供流动性或借贷,获得代币奖励,实现收益最大化。
#### **收益来源**
```
1. 交易手续费
- Uniswap: 0.3%
- Curve: 0.04%
2. 借贷利息
- 存款利息
- 借款利率差
3. 代币激励
- COMPCompound
- AAVEAave
- UNIUniswap
4. 挖矿奖励
- 质押LP Token
- 获得项目代币
```
#### **APY计算**
```
APY = (1 + APR/365)^365 - 1
APR年化收益率
- 交易手续费收益
- 借贷利息收益
- 代币激励收益
示例:
APR = 30%
APY = (1 + 0.3/365)^365 - 1 = 34.97%
```
#### **策略示例**
```go
type YieldFarm struct {
Pool string
TVL float64 // 总锁仓量
DailyVolume float64 // 日交易量
FeeRate float64 // 手续费率
RewardAPR float64 // 代币奖励APR
}
func (yf *YieldFarm) CalculateAPY() float64 {
// 手续费收益
dailyFee := yf.DailyVolume * yf.FeeRate
yearlyFee := dailyFee * 365
feeAPR := yearlyFee / yf.TVL
// 总APR
totalAPR := feeAPR + yf.RewardAPR
// APY
APY := math.Pow(1+totalAPR/365, 365) - 1
return APY
}
func main() {
// Uniswap ETH/USDT 池
pool := YieldFarm{
Pool: "ETH/USDT",
TVL: 10000000, // 1000万
DailyVolume: 5000000, // 500万
FeeRate: 0.003, // 0.3%
RewardAPR: 0.1, // 10% 代币奖励
}
apy := pool.CalculateAPY()
fmt.Printf("APY: %.2f%%\n", apy*100)
}
```
---
### 7. 闪电贷Flash Loan
#### **定义**
无需抵押,在一笔交易内借款并还款的贷款。
#### **特点**
```
1. 无需抵押
2. 必须在同一笔交易内还款
3. 如果还款失败,整个交易回滚
4. 手续费0.09%Aave
```
#### **应用场景**
**1. 套利**
```solidity
// 套利示例
function executeArbitrage() external {
// 1. 闪电贷借入 1000 ETH
uint256 loanAmount = 1000 ether;
flashLoan(loanAmount);
// 2. 在 Uniswap 用 ETH 买 USDT
// 价格1 ETH = 2000 USDT
uint256 usdtAmount = uniswap.swap(loanAmount);
// 3. 在 SushiSwap 用 USDT 买回 ETH
// 价格1 ETH = 2010 USDT
uint256 ethAmount = sushiswap.swap(usdtAmount);
// 4. 还款 1000 ETH + 手续费
uint256 repayment = loanAmount * 10009 / 10000;
repay(repayment);
// 5. 利润 = ethAmount - repayment
// 如果利润 < 0交易回滚
}
```
**2. 清算**
```solidity
// 清算获利
function liquidate(address borrower) external {
// 1. 闪电贷借入 USDT
flashLoan(10000 * 1e6);
// 2. 清算借款人
// 清算折扣5%
uint256 collateral = liquidateBorrower(borrower);
// 3. 卖掉抵押品
uint256 usdtReceived = sellCollateral(collateral);
// 4. 还款 + 赚取清算奖励
repay(10000 * 1e6);
// 利润 = usdtReceived - 10000 USDT + 清算奖励
}
```
**3. 更改DeFi头寸**
```solidity
// 无需本金切换协议
function switchProtocol() external {
// 1. 闪电贷借入资金
flashLoan(amount);
// 2. 从 Aave 取出抵押品
aave.withdraw(collateral);
// 3. 存入 Compound
compound.deposit(collateral);
// 4. 还款
repay(amount);
// 实现无本金迁移
}
```
---
### 8. DEX聚合器1inch
#### **工作原理**
```
1. 用户发起交易请求
- 输入1 ETH
- 输出:期望获得最多 USDT
2. 聚合器查询多个DEX
- Uniswap: 2000 USDT
- SushiSwap: 1995 USDT
- Curve: 1998 USDT
3. 拆分订单(最优路径)
- Uniswap: 0.6 ETH → 1201 USDT
- SushiSwap: 0.4 ETH → 799 USDT
- 总计2000 USDT
4. 执行交易
```
#### **路径优化算法**
```go
type DEX struct {
Name string
Reserve0 float64
Reserve1 float64
Fee float64
}
type Router struct {
Dexs []DEX
}
// 计算最优路径
func (r *Router) FindBestRoute(
amountIn float64,
) []struct {
Dex string
Amount float64
} {
type Route struct {
Dex string
AmountIn float64
AmountOut float64
}
var routes []Route
// 1. 单DEX路由
for _, dex := range r.Dexs {
amountOut := r.calculateOutput(dex, amountIn)
routes = append(routes, Route{
Dex: dex.Name,
AmountIn: amountIn,
AmountOut: amountOut,
})
}
// 2. 多DEX拆分二分查找最优解
for _, dex1 := range r.Dexs {
for _, dex2 := range r.Dexs {
if dex1.Name == dex2.Name {
continue
}
// 二分查找最优拆分
left, right := 0.0, amountIn
for i := 0; i < 50; i++ {
mid1 := (left + right) / 2
mid2 := amountIn - mid1
out1 := r.calculateOutput(dex1, mid1)
out2 := r.calculateOutput(dex2, mid2)
total := out1 + out2
routes = append(routes, Route{
Dex: dex1.Name + " + " + dex2.Name,
AmountIn: amountIn,
AmountOut: total,
})
}
}
}
// 3. 选择最优
sort.Slice(routes, func(i, j int) bool {
return routes[i].AmountOut > routes[j].AmountOut
})
return routes[0]
}
```
---
### 9. 借贷协议Aave、Compound
#### **工作原理**
```
存款人:
1. 存入资产如USDT
2. 获得利息
3. 获得aTokenAave或cTokenCompound
借款人:
1. 存入抵押品如ETH
2. 根据抵押率借款
3. 支付利息
```
#### **利率模型**
```solidity
// Compound 利率模型
function getBorrowRate(uint256 cash, uint256 borrows) public view returns (uint256) {
uint256 utilization = borrows * 1e18 / (cash + borrows);
// 分段利率
if (utilization < kink) {
// 低利用率:利率增长慢
return baseRate + utilization * multiplier;
} else {
// 高利用率:利率增长快
uint256 normalRate = baseRate + kink * multiplier;
uint256 excessUtil = utilization - kink;
return normalRate + excessUtil * jumpMultiplier;
}
}
// 示例:
// 利用率 < 80%: 利率 = 2% + 利用率 * 10%
// 利用率 > 80%: 利率快速增长到 20%+
```
**利用率Utilization Rate**
```
利用率 = 总借款 / (总存款 + 总借款)
例如:
存款1000万 USDT
借款800万 USDT
利用率800 / 1000 = 80%
利率与利用率的关系:
- 利用率越高,利率越高
- 鼓励存款,抑制借款
```
---
#### **抵押率Collateral Factor**
```
抵押率决定了可以借多少
例如:
- ETH抵押率75%
- 存入10 ETH价值$20,000
- 可借款20,000 * 75% = $15,000
不同资产抵押率:
- ETH: 75%
- WBTC: 70%
- USDC: 80%
- SHIB: 40%(高风险资产)
```
---
### 10. 清算Liquidation
#### **清算机制**
```
健康因子Health Factor
HF = (抵押品价值 * 抵押率) / 借款价值
HF > 1: 安全
HF < 1: 可被清算
清算奖励5-15%(激励清算人)
```
#### **清算示例**
```solidity
// 清算逻辑
function liquidate(
address borrower,
address collateralAsset,
address debtAsset,
uint256 debtToCover
) external {
// 1. 检查健康因子
uint256 healthFactor = getHealthFactor(borrower);
require(healthFactor < 1e18, "Cannot liquidate");
// 2. 计算可清算数量
uint256 maxDebt = getMaxDebt(borrower);
uint256 debt = min(debtToCover, maxDebt);
// 3. 清算人偿还债务
IERC20(debtAsset).transferFrom(msg.sender, address(this), debt);
// 4. 给清算人抵押品折扣5%
uint256 collateral = (debt * 105) / 100;
IERC20(collateralAsset).transfer(msg.sender, collateral);
// 5. 更新借款人状态
updateBorrowerState(borrower, debt, collateral);
}
```
**示例**
```
借款人状态:
- 存入10 ETH$20,000
- 借款15,000 USDT
- ETH价格跌到 $1,800
- 抵押品价值:$18,000
健康因子:
HF = (18,000 * 0.75) / 15,000 = 0.9 < 1
可被清算:
- 清算人偿还 15,000 USDT
- 获得抵押品15,000 * 1.05 = 15,750 USDT价值
- 实际获得15,750 / 1,800 ≈ 8.75 ETH
- 清算人利润0.75 ETH$1,350
```
#### **避免被清算**
```
1. 监控健康因子
- 设置告警HF < 1.2
- 及时还款或增加抵押品
2. 选择稳定抵押品
- 避免高波动资产
- 优先选择ETH、WBTC
3. 不要满仓借款
- 保持安全边际
- 借款不超过50%
4. 使用DeFi Saver等工具
- 自动化风险管理
- 自动还款/增加抵押
```
---
## 结合简历的面试题
### 1. 高并发与AMM
**面试官会问**
> "你做过50k+ QPS的消费券系统AMM DEX如何处理高并发"
**参考回答**
```
传统高并发Web2
- 消费券抢购50k QPS
- 使用Redis缓存
- 使用消息队列削峰
- 使用分布式锁
AMM DEX高并发Web3
- 区块链TPS限制Ethereum: 15 TPS
- 解决方案:
1. Layer2
- Arbitrum: 4000+ TPS
- Optimism: 2000+ TPS
- 使用Rollup扩容
2. 交易池管理
- Gas Price竞价
- 优先级队列
- 交易打包优化
3. MEV矿工可提取价值
- 套利机器人
- 三明治攻击
- 需要抗MEV设计
4. 链下撮合 + 链上结算
- LoopringZK-Rollup DEX
- dYdX链下订单簿
```
---
### 2. 低代码与智能合约开发
**面试官会问**
> "你做过低代码平台,智能合约开发有哪些低代码/无代码方案?"
**参考回答**
```
传统低代码:
- aPaaS平台
- 可视化搭建
- 模板+配置
Web3低代码
1. 智能合约模板
- OpenZeppelin Wizard
- 拖拽式生成合约
- 自动安全审计
2. 无代码部署
- Thirdweb
- 无需写代码部署NFT、Token
- 一键发币
3. 可视化IDE
- Remix IDE
- 图形化调试
- 在线编译部署
4. SDK封装
- Ethers.js
- Web3.js
- 简化合约交互
对比:
- 传统:降本增效
- Web3降低开发门槛加速生态发展
```
---
### 3. 营销系统与DeFi激励
**面试官会问**
> "你做过营销表达和策略玩法DeFi的激励机制如何设计"
**参考回答**
```
传统营销:
- 消费券
- 满减活动
- 会员等级
DeFi激励
1. 流动性挖矿
- 提供流动性获得代币奖励
- 类似消费券:吸引用户
2. 交易挖矿
- 交易即挖矿
- 类似满减:降低交易成本
3. 治理权
- 持有代币可投票
- 类似会员:参与决策
4. 质押奖励
- 锁仓获得高收益
- 类似定期存款
关键差异:
- 传统:中心化决策
- DeFi代币化激励社区治理
```
---
## DeFi面试加分项
### 1. 实战经验
- 参与过DeFi项目开发
- 熟悉主流协议Uniswap、Aave、Compound
- 了解链上数据分析Dune Analytics
- 有MEV研究经验
### 2. 技术深度
- 理解AMM数学原理
- 了解利率模型设计
- 熟悉预言机机制
- 掌握Gas优化技巧
### 3. 安全意识
- 智能合约审计经验
- 了解常见漏洞(重入攻击、闪电贷攻击)
- 熟悉安全工具Slither、MythX
### 4. 行业理解
- DeFi生态全景
- 协议间组合性
- 监管趋势
- 风险管理