在同一台 L2 上做清算,参数越长付得越多。Aave 在 L2 部署里额外提供了一个入口合约,把清算所需的五个参数塞进两段 bytes32,官方文档写明这条路的目的是压缩 calldata 体积以降低交易成本,并给出一个辅助合约帮你把普通参数转成紧凑格式。理解这个压缩到底压掉了什么,才能判断它省在哪、又在哪些情况下反而添麻烦。
先看普通清算函数的参数表:抵押资产地址、债务资产地址、借款人地址、要代偿的债务额、是否接收凭证,五个参数里有两个是二十字节的地址,加上下一个三十二字节的金额与一个布尔,展开在 calldata 里是几十个字节的长度。合约的输入编码本身还会带函数选择器与偏移量,这些固定开销在 L2 上会被计入数据成本——L2 把交易数据发布到上一层,数据字节是明码标价的项目。
紧凑版把这些字段重排进两个三十二字节槽。第一段里,抵押资产用它在协议资产列表里的下标占前十六位、债务资产下标占接下来十六位,剩下的位放借款人地址;第二段里,低一百二十八位放压缩后的代偿金额,第一百二十八位放那个布尔开关。合约在执行时把这两段解码还原成原来的参数,校验和清算逻辑本身完全一致。可以看到压缩的核心思路是用小整数下标替代长地址:一个资产的地址占二十字节,它在列表里的序号只需占一小段固定位宽,代价是参数从自解释变成了依赖状态。
依赖状态就是它的全部风险来源。资产列表的下标不是代币的身份证,而是这个部署里当前登记的顺序。同样的代币在不同市场的列表位置上可能不同,同一市场在新增资产后各资产下标也不该变动,但任何把下标算错的输入都会指向另一个资产——清算调用的校验逻辑会在抵押、债务与用户组合不匹配时回滚,所以真正的危险不是悄悄清算了别人,而是你的交易白白烧掉一笔燃料。用官方辅助合约生成参数正是为这件事兜底,它从合约状态里读列表,而不是让你手填序号。
第二个细节是金额的压缩。代偿金额被截成一百二十八位,并约定当它取该类型的最大值时展开成完整无符号整数的最大值,对应官方文档里那个填最大值即按清算比例尽可能多清算的用法。绝大多数仓位的债务额远在一百二十八位范围内,但这意味着编码工具需要自己判断上界,写死长度的脚本在极端仓位上可能构造出错误输入。
再来看省下的钱归谁。在多数 rollup 上,calldata 字节的成本最终以某种形式回收给 sequencer 与上一层,因此压缩参数省的是发起方自己的支出;清算本来就是抢跑生意,利润差往往就是几十个字节的成本差,多个清算者同时盯一个仓位时,谁的输入更短、谁能在同样出价下留更多利润,这也是这类优化在清算场景优先落地的原因。同理,这类入口一般不做用户界面的默认路径,官方文档也说明辅助合约只用于帮助用户与前端生成参数——普通存款、借款的输入长度不足以让压缩划算,反而牺牲可读性。
实操上有几条边界值得注意。第一,同一个仓位在主池入口和 L2 紧凑入口上执行结果应当一致,若你同时接了两条路径,务必用同一份模拟环境跑一遍,避免两个入口在你的日志里被当成两笔独立清算重复统计。第二,压缩参数在区块浏览器里不可读:你看到的是一段高熵字节,事后核对必须回用解码工具或事件日志,事件仍按原始参数发出,这也是判断是否被抢先清算的最可靠依据。第三,如果协议在这个 L2 部署上做过资产迁移或列表调整,任何长期运行的机器人应改成每轮从辅助合约重读下标,而不是缓存旧值。
最后一个视角是把这类优化放回 L2 的账本结构里看。L2 上每笔交易的成本大致分成执行与数据两块,参数压缩动的是数据那块,与 gas 单价、燃料上限无关。所以它和优先费优化、批量合并调用是三件互补的事:想大幅压缩清算成本,通常要同时把下标化参数、多仓位打包和私交易通道三件事都做一遍,只做其中任何一件,效果都会被另外两块的开销掩盖。
要提醒的是,紧凑入口是优化,不是新语义。抵押品估值、健康因子、清算比例、协议费等规则与主池完全一致,任何以为换入口能改扣减口径的想法都是误解。把机制读清楚之后,你省下的每一分钱都来自编码,而不是来自规则的空子。
本文只讨论合约参数编码与成本结构,示例数字不构成收益承诺,本文内容不构成投资建议;清算与借贷存在合约及市场风险,操作前请核对官方合约文档并自担风险。

发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。