{"content":{"title":"Jarvis Network闪贷及重入攻击分析","body":"![image.png](https://img.learnblockchain.cn/attachments/2023/01/zemMuPfi63c906abef5f9.png)\r\nUTC时间2023年1月15日下午05:43:37，根据Numen的链上监测，Jarvis_Network项目遭到攻击，损失663101个MATIC。具体交易可查看https://polygonscan.com/tx/0x0053490215baf541362fc78be0de98e3147f40223238d5b12512b3e26c0a2c2f\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/T7f4C94R63c906f424d90.png)\r\n\r\n通过对调用栈的分析，该笔交易涉及到多次token转账，导致调用栈较长。我们的分析表明调用过程中存在可重入逻辑。重入过程显示，同一个合约的同一个函数调用，传入参数相同，但重入前后返回值差异很大。\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/GBDqzRBX63c90719f34f1.png)\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/FTBxTe5163c9078b3e26d.png)\r\n\r\n\r\n重入发生在https://polygonscan.com/address/0xfb6fe7802ba9290ef8b00ca16af4bc26eb663a28\r\n合约的 remove_liquidity 函数中。remove_liquidity 函数在移除流动性时将代币返回给用户。由于 Polygon 和 EVM 是同构链，当向 MATIC 合约转入代币时，它进入了合约重入。对调用堆栈的可重入部分进行了详细分析。\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/xht1Nfqa63c907cca4c64.png)\r\n\r\n分析的第一个合约是 getUnderlyingPrice ：https://polygonscan.com/address/0xcc6aa628516bb46391b05b16e5058c877461cc76 \r\n这是一个合乎逻辑的合约，但不是开源的。\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/4V1kVSUj63c907fec2a8e.png)\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/pkeHnDVZ63c90806c8d28.png)\r\n根据slot，我们得到v1 = 0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d和wtoken = 0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270。然后我们进入if分支，通过slot找到_oracles[v1] = 0xacf3e1c6f2d6ff12b8aee44413d6834774b3f7a3。我们继续进入里面的else分支，调用0xacf3e1c6f2d6ff12b8aee44413d6834774b3f7a3合约的getUnderlyingPrice函数。0xacf3e1c6f2d6ff12b8aee44413d6834774b3f7a3对应的逻辑合约是0x3803527dcd92ac3e72a0a164db82734daba47fac，这个合约也没有开源。\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/KeYWR3in63c908369f6b4.png)\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/jLd25D6G63c9083c8ea2c.png)\r\n\r\n攻击涉及内置计算，因为它涉及重入，并且一些变量必须在传输发生后计算。这部分代码没有涉及到外部变量，所以问题应该不在这里。其中，函数 0x9de 被调用。\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/EDjZNIKj63c9084da65dc.png)\r\n\r\n变量 varg0 是传入的令牌地址，即 0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d。对应的_poolOf[v0]为0xfb6fe7802ba9290ef8b00ca16af4bc26eb663a28。然后分析这个合约的get_virtual_price函数。该函数的代码如下：\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/VuXvYCvm63c90866a2938.png)\r\n\r\n\r\n变量self.token还是0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d，除数就是这个token的总流通量。\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/19hKdgWa63c9087533100.png)\r\n\r\n观察到变量D影响了get_xcp的返回值，重入发生在 remove_liquidity 函数中，然后进行分析。该函数的详细代码如下：\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/V2SnfEaV63c9088153a41.png)\r\n\r\n注意到调用前后 get_virtual_price 返回值的变化。\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/tPFd9tdw63c908b23ad2c.png)\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/01/qz02dAfu63c9088c6e742.png)\r\n\r\nself.D的变化发生在transfer之后，当攻击者移除流动性时，MATIC 将转移到攻击者的合约中，fallback回调时，首先检查 0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d 的价格，由于self.D在转账后更新，导致之前的价格获取错误。\r\n\r\n去除流动性的过程如下：\r\n1. 销毁用户的LP\r\n2. 发送用户的抵押资金\r\n3. 更新self.D变量。\r\n\r\nSelf.D 用于计算价格，并且在增加流动性时也会更新。然而，在这种情况下，攻击者拥有更多的流动资金。根据self.D的计算公式self.D = D - D * amount / total_supply，正常情况下计算self.D的值会比较小，amount和total_supply几乎相等。\r\n\r\n然而，由于攻击者重新进入并在原始价格的基础上增加了 10 倍的借贷，所以 self.D 的价值在流动性增加时增加，而在移除时没有及时更新。\r\n\r\nremove_liquidity 方法包括一个不可重入锁（'lock'）以防止该方法被重新进入，但是当攻击者重新进入另一个合约以借入资金时该锁不起作用。"},"author":{"user":"https://learnblockchain.cn/people/12138","address":null},"history":null,"timestamp":1674119587,"version":1}