permitDeposit、EIP-2612链下签名`、无ETH场景、赞助商代付Gas。1.背景与合约角色XZXToken:OpenZeppelinERC20+ERC20Permit,名称与EIP-712域一致(如"xzx")。TokenBankV2:deposi
permitDeposit、EIP-2612 链下签名`、无 ETH 场景、赞助商代付 Gas。
ERC20 + ERC20Permit,名称与 EIP-712 域一致(如 "xzx")。deposit / withdraw / permitDeposit 中的 amount 均为最小单位(与标准 ERC20 一致)。permitDeposit:在一笔对 Bank 的调用内,依次执行代币的 permit 与 transferFrom(owner, Bank, amount),并更新 deposits[owner]。approve(Bank),再 deposit —— 通常需要用户自己发链上交易并付 Gas。spender(此处为 Bank 地址)在一定 value 内动用代币;第三方可把签名提交上链执行 permit,再 transferFrom。permitDeposit 的价值:把「授权 + 从用户划币进 Bank + 记账」串成 一次对 Bank 的调用;用户侧可只做 签名,不必自己发 approve 交易。permitDeposit 在做什么(逐步)对应实现逻辑(概念与代码一致):
amount > 0、owner != address(0)。token.balanceOf(owner) >= amount(避免 permit 成功后转账失败)。IERC20Permit(token).permit(owner, address(Bank), amount, deadline, v, r, s)
allowance(owner, Bank) 都在 代币合约 内完成。token.transferFrom(owner, address(Bank), amount)
deposits[owner] += amount,首存写入 depositors,emit Deposit。重要澄清:验签不在 Bank
Bank 只转发调用;EIP-2612 签名验证在 Token 的 permit 中完成。
Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)
PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")
| 字段 | 说明 |
|---|---|
owner |
持币用户地址(签名私钥对应地址) |
spender |
必须为 TokenBankV2 部署地址 |
value |
最小单位,且必须等于 permitDeposit 的 amount |
nonce |
链上读取 token.nonces(owner)(每笔成功 permit 后递增,防重放) |
deadline |
Unix 秒;过期则 permit 失败 |
structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonce, deadline))DOMAIN_SEPARATOR:链上 IERC20Permit(token).DOMAIN_SEPARATOR()(与代币合约地址、链 ID、name/version 绑定)digest = keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, structHash))digest 做 secp256k1 签名,得到 (v, r, s)任意账户可调:
bank.permitDeposit(owner, amount, deadline, v, r, s)
其中 owner, amount, deadline 必须与签名时一致。
permitDeposit 不能让用户用 XZX 直接当 Gas:ERC-20 不是原生 Gas 币;合约也无法从用户钱包里「自动扣 ETH」。approve,常配合 Relayer 由别人代发 permitDeposit 交易。验签位置 vs Gas:
| 项目 | 说明 |
|---|---|
| 验签发生在哪里 | 代币合约 permit |
| Gas 谁付 | 发送 permitDeposit 交易的外部账户(或 AA/Paymaster 体系下的赞助方) |
permitDeposit 的交易(见下节 赞助商 D),或 账户抽象 + Paymaster 等方案,或给用户少量入门 ETH。amount(最小单位)、deadline,读取 nonces(A) 等。owner=A, spender=Bank, value=amount, nonce, deadline)签名,得到 (v,r,s)。{owner, amount, deadline, v, r, s} 交给 dApp / 后端(HTTPS 等,不必上链)。to = Bank data = permitDeposit(A, amount, deadline, v, r, s) permit 验证 A 的签名;transferFrom 从 A 扣 XZX 到 Bank;Bank 记 deposits[A]。permitDeposit 单独保证。deadline 前可被任何知道参数的人提交;deadline 不宜过长。nonce 用过后旧签名失效;参数被篡改则 permit 验签失败。deposit 的对比| 项目 | deposit前需链上 approve |
permitDeposit |
|---|---|---|
| 用户链上操作 | 通常需用户自己 approve(付 Gas) |
用户只需链下签 Permit;上链可由 Relayer 代发 |
amount 含义(当前项目) |
最小单位 | 最小单位(= Permit 的 value) |
链下:用户 A 对 Permit 签名。
链上:Relayer / 赞助商 D 付 Gas 调 permitDeposit;验签在 Token;扣 XZX Token 从 A;Bank 只编排调用与记账。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!