ERC-4626金库用资产换份额,转换结果通常向下舍入。成熟金库中一次舍入损失很小;空金库却没有稳定汇率锚点。攻击者先存入极小资产取得份额,再直接向金库捐赠,把每份额代表的资产抬高,后来的小额存款可能被舍入成零份额。
| 阶段 | 金库资产 | 总份额 | 对后来存款的影响 |
|---|---|---|---|
| 初始 | 0 | 0 | 汇率尚未形成 |
| 攻击者小额首存 | 很少 | 很少 | 攻击者取得初始份额 |
| 直接捐赠 | 大幅增加 | 不增加 | 每份额价格被推高 |
| 受害者存款 | 再增加 | 可能铸得0 | 资产进入金库却无份额 |
攻击成立所需的三个条件
- 攻击者可在空金库先存入极少资产,再直接捐赠资产抬高每份额价格,使后续小额存款因向下舍入得到零或极少份额。
- 虚拟资产与虚拟份额在汇率计算中提供初始锚点,decimals offset还能提高份额精度并让攻击捐赠的一部分落入金库。
- ERC-4626的previewDeposit等函数用于预估当前状态下结果,但交易执行前状态仍可能变化,集成方需另加最小份额或滑点约束。
问题来自汇率和舍入组合
捐赠不是deposit,不会为捐赠者新铸份额,却改变totalAssets。若公式计算受害者应得0.8份并向下取整为0,受害者把资产送入金库却没有可赎回凭证。攻击者随后凭自己的份额赎回,就可能吸收受害者价值。
虚拟偏移怎样提高攻击成本
实现可以在计算中加入虚拟资产和虚拟份额,给空金库一个初始锚点;提高份额decimals offset还能让小额存款得到更多最小份额单位。攻击者捐赠的一部分会被虚拟份额稀释,想把汇率推到危险区间需要付出更高且难以回收的成本。
用户端仍要做滑点保护
previewDeposit只按调用时状态估算份额,交易上链前汇率可能被其他操作改变。路由器或前端应让用户指定minimum shares,执行时不满足就revert。对空金库、极低totalSupply和异常捐赠,应显示更强警告并先小额验证。
不盈利的攻击仍可能造成破坏
“只要攻击不赚钱就完全安全”不成立,攻击者可能愿意付费阻断用户或制造坏账;“preview返回非零就一定得到这些份额”也不成立,状态竞争会改变结果。协议防护与交易级滑点检查必须同时存在。
DeFi仓位风险可结合Aave清算比例理解;未知合约先执行连接检查,链上状态证据可参考eth_getProof验证。
存款交易必须带的护栏
- 检查实现是否有虚拟资产或最小流动性
- 比较totalAssets、totalSupply和份额decimals
- 存款前调用preview并设置最小份额
- 监控首存、捐赠和异常汇率跳变
- 不要把ERC-4626兼容当成安全审计结论
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。