Permit2 合约
Permit2 是共享的代币授权管理器。用户只需将代币授权给 Permit2 一次,然后可以向特定的授权对象授予限定范围的权限。 概念概述请参阅 Permit2 概念。核心函数
approve
授予授权对象通过 Permit2 代表调用者转移特定代币的权限。function approve(
address token,
address spender,
uint160 amount,
uint48 expiration
) external;
| 参数 | 类型 | 描述 |
|---|---|---|
token | address | 要授权的 ERC-20 代币 |
spender | address | 被授予权限的地址(例如 Universal Router) |
amount | uint160 | 授权对象可转移的最大数量 |
expiration | uint48 | 权限过期的 Unix 时间戳 |
const permit2 = new ethers.Contract(PERMIT2_ADDRESS, PERMIT2_ABI, signer);
await permit2.approve(
tokenAddress,
UNIVERSAL_ROUTER,
ethers.MaxUint160, // 最大数量
Math.floor(Date.now() / 1000) + 365 * 86400 // 1 年有效期
);
allowance
查询给定的 owner-token-spender 三元组的当前授权信息。function allowance(
address owner,
address token,
address spender
) external view returns (
uint160 amount,
uint48 expiration,
uint48 nonce
);
| 返回值 | 类型 | 描述 |
|---|---|---|
amount | uint160 | 剩余授权数量 |
expiration | uint48 | 过期的 Unix 时间戳 |
nonce | uint48 | 此授权的当前 nonce 值 |
const [amount, expiration, nonce] = await permit2.allowance(
userAddress,
tokenAddress,
UNIVERSAL_ROUTER
);
const needsApproval = amount < requiredAmount || expiration < Math.floor(Date.now() / 1000);
ABI
[
"function approve(address token, address spender, uint160 amount, uint48 expiration)",
"function allowance(address owner, address token, address spender) view returns (uint160 amount, uint48 expiration, uint48 nonce)"
]
集成模式
async function ensurePermit2Approval(signer, tokenAddress, spender, requiredAmount) {
const permit2 = new ethers.Contract(PERMIT2_ADDRESS, PERMIT2_ABI, signer);
const owner = await signer.getAddress();
// 1. 检查现有的 Permit2 子授权
const [amount, expiration] = await permit2.allowance(owner, tokenAddress, spender);
const now = Math.floor(Date.now() / 1000);
if (amount >= requiredAmount && expiration > now) {
return; // 已授权
}
// 2. 检查对 Permit2 的 ERC-20 授权
const token = new ethers.Contract(tokenAddress, ERC20_ABI, signer);
const tokenAllowance = await token.allowance(owner, PERMIT2_ADDRESS);
if (tokenAllowance < requiredAmount) {
const tx = await token.approve(PERMIT2_ADDRESS, ethers.MaxUint256);
await tx.wait();
}
// 3. 授予 Permit2 子授权
const tx = await permit2.approve(
tokenAddress,
spender,
ethers.MaxUint160,
now + 365 * 86400
);
await tx.wait();
}