智能合约漏洞案例,Palmswap 90 万美元漏洞分析
据Safful安全团队情报,2023 年 7 月 25 日,BSC 链上的 Palmswap 项目遭到攻击,攻击者获利超 90 万美元。Safful安全团队介入分析后将结果分享如下:
相关信息
Palmswap v2 提供了一个高流动性、功能强大且用户友好的去中心化杠杆交易平台。其中 PLP 是 Palmswap 交易平台的流动性提供者代币,它由用于杠杆交易的 USDT 资产指数组成。PLP 可以用 USDT 铸造,然后用 USDT 烧回去。铸造和重新燃烧的价格是用指数中资产的总价值(包括未平仓头寸的损益)除以 PLP 供应量得到。
以下是本次攻击涉及的相关地址:
攻击者 EOA 地址:
0xf84efa8a9f7e68855cf17eaac9c2f97a9d131366
攻击合约地址:
0x55252a6d50bfad0e5f1009541284c783686f7f25
攻击交易:
https://bscscan.com/tx/0x62dba55054fa628845fecded658ff5b1ec1c5823f1a5e0118601aa455a30eac9
被攻击的合约地址:
0xd990094a611c3de34664dd3664ebf979a1230fc1
0xa68f4b2c69c7f991c3237ba9b678d75368ccff8f
0x806f709558cdbba39699fbf323c8fda4e364ac7a
攻击核心点
在 Palmswap 交易平台中,PLP 代币的价格基于金库中的 USDT 数量和 PLP 代币总供应量。
而如果金库合约没有开启管理员模式的话,任何用户都可以通过直接用 USDT 购买 USDP 代币的方式来提高金库中的 USDT 数量,且不改变 PLP 代币的总供应量,这将导致攻击者可以利用闪电贷恶意操控 PLP 代币的价格获利。
具体细节分析
- 攻击者首先通过闪电贷借出 3,000,000 枚 USDT,并用其中 1,000,000 枚 USDT 去添加流动性,铸造 PLP 代币。
- 在添加流动性的函数中,攻击者先转入 USDT,并调用金库合约的 buyUSDP 函数购买 USDP 代币,之后用通过购买的 USDP 代币数量计算所需铸造的 PLP 代币数量。
此处攻击者用 1,000,000 枚 USDT 购买了 996,769 枚 USDP,并铸造出了约 996,324 枚 PLP 代币。
- 接着攻击者调用金库合约中的 buyUSDP 函数,该函数在通过管理员验证后可以直接用 USDT 购买 USDP 代币,同时会增加金库合约中的 USDT 代币储备。
但是由于金库合约并没有开启管理员模式,导致任何用户都可以直接调用金库合约的 buyUSDP 函数来购买 USDP 代币,所以攻击者直接将闪电贷剩余的 2,000,000 枚 USDT 转入金库合约并购买 USDP 代币。
- 紧跟着,攻击者立马移除流动性,此时会燃烧掉所有的 PLP 代币并卖出 USDP 代币。但是可以发现,攻击者燃烧掉 996,311 枚 PLP 代币却获取了 1,962,472 枚 USDP 代币。
这是由于在上一步购买 USDP 后,金库中的 USDT 代币数量突然暴增,而 PLP 代币的价格基于金库中 USDT 的余额进行计算的,因此 PLP 代币的价格也被拉高,使得攻击者获取了超出预期的 USDP 代币。
- 最后,攻击者调用金库合约的 sellUSDP 函数,卖出第三步中获取的剩余 USDP 代币,换成 USDT 后归还闪电贷,获利离场。
总结
本次攻击事件是由于核心函数的权限管控功能未开启,并且流动性代币的价格计算模型设计得过于简单,仅取决于金库中的 USDT 代币数量和总供应量,导致攻击者可以利用闪电贷来恶意操控价格以获取非预期的利润。Safful安全团队建议项目方设计流动性代币的价格模型时,加入多方面因素进行限制,例如添加流动性的时间因子等,并且严格限制核心函数的权限。