Q17 · 前端与链交互

前端和合约交互为何要先 approve?

ERC20approve授权有 Demo

⚡ 速记答案(30 秒)

  • ERC20 标准:合约不能随意划走用户 Token,只能划走用户事先授权(approve)给它的额度
  • 流程:用户先 approve(DEX合约, amount) → 再调用 swap/stake 等函数;合约内部用 transferFrom 扣用户额度
  • 好处:提升安全性、可精细控制每个合约的最大可用额度

📖 详细讲解

为什么需要 Approve


ERC20 设计原则:用户资产由用户控制


合约无法直接 transfer 用户的代币,必须:

1. 用户先调用 approve(spender, amount) 授权额度

2. 合约再调用 transferFrom(user, to, amount) 转账


完整交互流程


1. 检查 allowance (已授权额度)
2. 如果额度不足,调用 approve
3. 等待 approve 交易确认
4. 调用目标函数 (swap/stake/...)
5. 合约内部执行 transferFrom

授权安全


无限授权风险:approve(MAX_UINT256) 方便但有风险

建议:只授权需要的额度,或使用 Permit2

💻 代码示例

Approve 流程示例
import { ethers } from 'ethers';

const ERC20_ABI = [
  'function approve(address spender, uint256 amount) returns (bool)',
  'function allowance(address owner, address spender) view returns (uint256)',
];

async function approveAndSwap(
  tokenAddress: string,
  spenderAddress: string,
  amount: bigint,
  signer: ethers.Signer
) {
  const token = new ethers.Contract(tokenAddress, ERC20_ABI, signer);
  const userAddress = await signer.getAddress();

  // 1. 检查当前授权额度
  const currentAllowance = await token.allowance(userAddress, spenderAddress);

  // 2. 如果额度不足,先授权
  if (currentAllowance < amount) {
    console.log('授权额度不足,正在授权...');
    const approveTx = await token.approve(spenderAddress, amount);
    await approveTx.wait();
    console.log('授权成功');
  }

  // 3. 执行 swap(示例)
  // const swapTx = await dex.swap(...);
}
💡
面试技巧:回答时先给出核心结论,再展开细节。如果有实际项目经验,一定要结合具体案例说明。