合约替操作你的资产:ERC-1207 的 DAuth 授权记录与到期时间戳 图 1
合约替操作你的资产:ERC-1207 的 DAuth 授权记录与到期时间戳 · 图 1

合约替操作你的资产:ERC-1207 的 DAuth 授权记录与到期时间戳

去中心化应用要替你管理资产时,最粗暴的做法是要用户的私钥,或者要用户把代币无限额度 approve 给协议合约。ERC-1207 提出第三条路:把授权本身写成资源合约里的一条记录。摘要的定义是——一套标准接口,允许智能合约之间在不接触用户私钥的前提下完成身份委托,可委托的内容包括访问和操作授权者数据与资产。这份文档创建于 2018 年 7 月 10 日,仓库记录状态为 Stagnant,属于长期无人推进的归档方案;动机部分把自己对标 OAuth,区别是 OAuth 依赖集中式授权服务器,DAuth 要在分布式环境里做同样的事,从而换来更高的可靠性与通用性。

五个角色与一条映射

规范的术语表先把舞台摆好:资源所有者是授权人(authorizer),资源合约提供数据和操作,客户端合约是接受授权方(grantee),二者的每次互动叫一次授权请求。授权的载体是一个叫 AuthInfo 的结构体,只有两个字段:funcNames,被授权合约可以调用的函数名列表;expireAt,以秒计的授权过期时间戳。存储形态是一条双层映射 userAuth:以(授权人地址,接受方合约地址)为键,值为那份 AuthInfo。也就是说资源合约内置一张授权台账,谁被谁授权、能进哪些门、几点关门,全部在链上可查——和 ERC-20 的 allowance 相比,这张台账记的不是额度,是函数名。

合约替操作你的资产:ERC-1207 的 DAuth 授权记录与到期时间戳 图 2
合约替操作你的资产:ERC-1207 的 DAuth 授权记录与到期时间戳 · 图 2

四个生命周期函数

授权接口有四个必选或可选函数。grant(address _grantee, string _invokes, uint _expireAt) 立授权,参数里的 _invokes 是一个字符串,规范写明它是以空格分隔的函数名列表。regrant 用同样的参数结构改授权,规范规定对同一个接受者重新授权会自动覆盖旧的 AuthInfo。revoke(address _grantee) 撤授权,规范规定成功的撤销必须触发 Revoke(authorizer, grantee) 事件,而 Grant(authorizer, grantee, invokes, expireAt) 事件在 grant 或 regrant 成功时都必须触发——权限的每一次立、改、撤都有链上日志可追。到期处理则完全交给时间:verify(address _authorizer, string _invoke) 在每次资源合约被客户端合约调用时检查这个用户在这个函数名上是否有效,规范对它和 updateCallableFuncNames 都加了同一句硬约束——只能返回成功或者抛错,不允许第三种结局,防的就是“含糊通过”。

双签名重载与管理员白名单

调用约定是这份设计里最工程化的部分。规范要求:所有被授权可调用的公开函数必须用重载实现两个同名版本,第一个是用户直接调的标准版本,第二个多带一个授权人地址参数,供客户端合约代表用户调用;资源合约的管理员还可以通过 updateCallableFuncNames 维护一份全局可调函数表,任何时刻允许跨合约调用的函数都同时受“全局表、个人 AuthInfo 白名单、时间戳”三层检查约束。三把锁少一把,设计者认为授权语义就不完整。

归档方案留下的对照价值

这份标准没有走出来,站在今天回看,原因依然回到信任边界:它把“谁能替你调用什么”写死在资源合约的存储里,但发起调用的仍然是客户端合约——verify 只能证明“该合约获得了授权且未过期”,无法证明合约内部逻辑不会滥用这两次调用的自由度;空格分隔的函数名字符串也比选择器级的权限粒度更粗糙,同名函数重载在两个版本里选错一个,授权含义就变了。后来的主流路线各自选了不同的切口:账户抽象把授权下沉到账户合约的策略层,权限枚举到函数选择器;ERC-20 的 approve 加 permit 走签名而非台账。读这份 Stagnant 文本的现实用处是给它三类后继做对照测试:任何“合约可以替你操作资产”的设计,都该回答同样三个问题——授权记录存在哪里、能不能查到确切的函数白名单、有没有硬过期时间。三问里只要有一问答不出链上地址,用户让渡的就不是权限,而是整段控制权。本文为机制说明,不构成任何投资建议。