在去中心化应用(DApp)的世界里,用户与智能合约的交互几乎都离不开一个关键步骤:授权,无论是DeFi协议中的代币转账,还是NFT市场的资产操作,用户都需要将自己的数字资产(如ERC20代币、ERC721/ERC1155 NFT)的控制权临时或永久地授予某个智能合约,理解DApp的授权机制,并掌握其背后的核心源码,是每一位区块链开发者深入构建安全、高效DApp的必修课,本文将带你从概念到实践,一步步拆解以太坊DApp的授权逻辑,并提供关键源码片段进行解析。
为什么需要授权?—— 从用户签名到合约调用
想象一个场景:你在一个去中心化交易所(如Uniswap)想用自己的USDT代币交换ETH,你点击“交换”按钮后,会发生什么?
- 直接调用失败:如果DApp直接调用
USDT合约的transferFrom函数,交易会失败,因为transferFrom要求调用者(即DApp的智能合约)拥有msg.sender(即你)的授权。 - 授权是桥梁:整个流程被巧妙地设计为两步:
- 第一步:授权,DApp首先引导你调用
USDT合约的approve函数,参数是授权的金额和接收方(即交易所的智能合约地址),你用自己的私钥对这笔交易进行签名广播,授权成功后,交易所合约就获得了从你账户中划走指定数量USDT的许可。 - 第二步:执行,DApp再调用交易所合约的
swap函数,该合约内部会调用USDT的transferFrom函数,将从你那里划来的USDT转入流动性池,并给你相应的ETH。
- 第一步:授权,DApp首先引导你调用
这个approve -> transferFrom的模式,就是ERC20标准授权机制的核心,也是DApp授权最经典的体现。
核心授权标准:ERC20 与 ERC721/1155
以太坊上最主流的资产标准都内置了授权机制,但其细节有所不同。
ERC20 (Fungible Tokens - 同质化代币)
ERC20的授权机制相对简单,主要依赖两个函数:
-
function approve(address spender, uint256 amount) external returns (bool);- 作用:授权
spender地址,可以最多从你的账户中转移amount数量的代币。 - 源码解析 (OpenZeppelin标准实现):
function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; }这个函数本身逻辑不复杂,它调用了内部的
_approve函数,该函数会更新一个名为allowances的映射。allowances[owner][spender]记录了owner授权给spender的额度。
- 作用:授权
-
function transferFrom(address from, address to, uint256 amount) external returns (bool);- 作用:从
from地址转移amount数量的代币到to地址,调用此函数需要满足两个条件:1)msg.sender已被from地址授权;2) 授权额度足够。 - 源码解析 (OpenZeppelin标准实现):
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; }关键在于
_spendAllowance函数,它会检查并扣除from地址对msg.sender的授权额度。function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } }
- 作用:从
ERC721 & ERC1155 (Non-Fungible & Semi-Fungible Tokens)
NFT的授权机制更为精细,因为它授权的是“资产所有权”本身,而不是可分割的数量。
-
ERC721:
function setApprovalForAll(address operator, bool approved) external;- 作用:批量授权,授权
operator地址可以管理你所有的NFT,这是一种“全有或全无”的授权,常用于游戏或NFT租赁协议。 - 源码解析:它会更新一个
isApprovedForAll的映射。
- 作用:批量授权,授权
function getApproved(uint256 tokenId) external view returns (address);
