撤销授权不等于收回已经发出去的钥匙副本。旧会话能继续付款,说明它手里那把钥匙在你撤销之前就已经被复制出去了。
去年有个做量化团队的朋友,代理跑得好好的,发现策略有风险就把代理权限撤了。结果第二天账上又少了 30 U,查了半天才发现是之前的一个测试会话还在跑——那个会话的 session key 他根本没撤销,只在钱包里点了个"断开连接"。
真相:你撤销的可能只是"连接",不是"支付权限"
大多数钱包里的"撤销授权"操作,有两种完全不同的含义:
情况 A:你撤销的是对某个 App 的"连接权限"
- 操作路径:钱包设置 → 已连接网站 → 断开
- 实际上只是从钱包界面移除了这个应用的可见性,并没有关掉它代你签名的能力
- 只要 session key 还在链上注册,对方仍然能发起交易
情况 B:你撤销的是具体的 session key 或 spending approval
- 需要发起一笔链上交易,把对应的授权合约状态改成"已撤销"
- 这笔操作要付 Gas 费,不是点一下就完事
很多钱包把这两个动作放在同一个按钮下,用户以为点一下就够了。
步骤 1:确认旧会话用的是哪种授权机制
不同代理钱包的授权模型不同,先搞清楚类型再动手:
- Session Key 模式(最常见):用户生成一个临时密钥,交给代理使用。代理拿着这把钥匙独立签名。撤销 session key 必须在链上或通过官方 SDK 执行。
- Spending Approval 模式:用户授权某个合约地址可以花指定数量的代币。撤销需要把授权额度改成 0。
- 应用层 token 模式:代理拿着一个 JWT 或 API token 来调用支付接口。撤销 token 只是在服务端把它的状态标记为失效。
完成标准: 明确你的代理工具用的是哪一种模式(查文档或问开发者)。
步骤 2:对症下药,真正关掉旧会话
情况 A:Session Key 模式
- 以 Privy 为例:调用
removeSessionSigners方法移除所有会话签名者。这会撤销所有代理的签名权限,只有用户自己才能继续操作钱包。 - 以 CHIPI 为例:通过 SDK 的
sessions.revokeSessionKey方法,传入要撤销的 session public key。 - 以 ZeroDev 为例:session key 的撤销本身就是一笔链上交易,执行后智能账户会拒绝任何超出已撤销权限的请求。
完成标准: 你发起了一笔链上交易,状态确认后,旧会话再发起支付会被拒绝,错误提示类似 SessionKeyRevoked 或 Unauthorized。
情况 B:Spending Approval 模式
- 用 Revoke.cash 或类似工具,找到对应的代币授权记录,点击撤销
- 撤销就是把授权额度设置为 0,这是一笔需要付 Gas 的链上交易
- 撤销后,被授权的合约地址不能再动用你的代币
完成标准: 在区块链浏览器或 Revoke.cash 上看到该授权的额度变为 0。
情况 C:应用层 token
- 去代理工具的后台或 Dashboard,找到"会话管理"或"API Keys"
- 手动删除或禁用对应的 session token
- 如果工具提供了 kill switch 功能,一键切断所有会话访问
步骤 3:如果已经发生了损失,查一下旧会话是否还在跑
- 打开代理工具的审计日志或交易记录,查一下撤销操作之后的时间段里,有没有来自旧会话的支付
- 在区块浏览器上查一下钱包地址的最近交易,看收款方和金额是否匹配旧会话的行为
高危提醒:链上 session key 的撤销是"防新不防旧"。如果旧会话在撤销之前已经签署了一笔交易并且没有广播(比如保存在本地队列里),撤销之后它仍然可以把这笔已签名的交易发出去。这和传统金融里"支票已经签好但还没寄出去"是一个道理——撤销授权管不了已经签过的文件。Vanguard 的 Full Agent Authorization 也有类似规则:代理撤销后,银行在收到书面通知后 10 天内仍然可以支付代理在撤销前签署的票据。
验证收尾
撤销完成后,做两件事:
- 直接用旧会话的凭证(session key 或 API token)发起一笔极小额的测试支付——应该被拒绝
- 如果是链上 session key,在区块浏览器上查到一笔
revoke类型的交易,确认状态是 Success
核验渠道: 在代理工具的 Dashboard 里看"活动会话"列表,旧会话应该从列表中消失或被标记为 Inactive。



