Wintermute 于Layer 2 遭攻击损失两千万枚OP代币_链圈子

今天要分享的是前阵子两千万枚OP 代币被攻击者盗取的事件。这个事件源自于Wintermute 造市商提供错误的地址给Optimism,导致代币转入没有人拥有的地址,后来却被攻击者抢先拥有这个地址。这篇内容我们将以这个事件为背景,介绍create 和create2 的概念。

Wintermute 于Layer 2 遭攻击损失两千万枚OP代币_链圈子

事件

起初,Optimism 基金会聘请Wintermute为其在中心化交易所上市的OP 代币提供流动性,协议的一部分是Wintermute 获得两千万枚OP 代币作为贷款(Wintermute 也提供50M USDC 作为抵押品)。这笔贷款应该是要转入Wintermute 在Optimism 链上的地址,但他们却提供已经部署在以太坊上许久的多签(multi-sig)Gnosis 金库地址: 0x4f3a 120E72C76c22ae802D129F599BFDbc31cb81。当Optimism 团队分别转移1 OP 和1M OP 作为测试时,Wintermute 却没有确认真的收到那些代币就和Optimism 团队确认了,所以剩下的19M 代币就又在5/27 转入了这个钱包地址。

Wintermute 于Layer 2 遭攻击损失两千万枚OP代币_链圈子
Optimism 团队先转了1 OP 和1M OP 作为测试,最后才转剩下的19M 代币。资料来源:Optimistic Explorer

Wintermute 提供的地址和普通的钱包地址(EOA, externally owned account)不同,他是一个合约地址,因此拥有在以太坊上这个合约的所有权不代表拥有其他EVM-compatible 链上相同地址的所有权。而这个地址当时在Optimism 链上还没有所有人。5/30 Wintermute 发现了这个错误,并通知了Gnosis 金库和Optimism。经过咨询后他们宣称只有他们自己能够复原那些资金,并计划在6/7 将资金取回。

Wintermute 的Gnosis 金库地址是2020 年由ProxyFactory 合约(0x76E2)的createProxy 这个function 创造的。这个ProxyFactory 合约在部署时没有指定的chainId,因此这个ProxyFactory 合约在每一条链上的合约地址都一样。此外创建proxy 合约时,创建出的proxy 合约其地址只受sender, nonce 这两个变数影响,所以在不同的链上只要用一样的sender 和nonce 就能得到相同地址的合约。

Wintermute 于Layer 2 遭攻击损失两千万枚OP代币_链圈子
创建Gnosis 金库合约的Factory 合约function。

攻击者(0x8BcF)在Optimism 链上也创立一个合约(0xE714)去呼叫Optimism 链上的ProxyFactory(0x76E2)的createProxy 创造地址直到找到0x4f3a 的那个地址。下图可以看到攻击者在一笔交易一次创建162 个地址,不断的重复这样的交易直到找到符合的地址,最后在这笔交易中创建了与Wintermute 在以太坊上一模一样的地址(0x4f3a)。

Wintermute 于Layer 2 遭攻击损失两千万枚OP代币_链圈子
攻击者一次创建162 个地址直到找到与Wintermute 一模一样的地址(0x4f3a)。

攻击者将1M OP 代币转入自己的地址,卖掉后获得大约720 ETH。几天后又将1M 代币转入Vitalik 的钱包地址(0x8da6)。最后将17M 代币以一次1M 的方式归还到Wintermute 指定的地址(0x2501),剩余的1M Optimism 团队也同意将总共2M 的OP 代币留给攻击者作为赏金。

Wintermute 于Layer 2 遭攻击损失两千万枚OP代币_链圈子
攻击后先将1M 代币转回自己的地址,4 天后将1M 代币转给Vitalik。

技术点create/create2

这边可以介绍两个以太坊在创建合约时可以用到的opcode — create 和create2。

  • create: new_address = hash(sender, nonce)
  • create2: new_address = hash(0xFF, sender, salt, bytecode)

create2 可以说是create 的升级版,在EIP-1014时被提出。create 的缺点是下一个被创建的合约地址是可以被预测的,因为nonce 会照顺序增加。而create2 则是使部署的地址独立于未来事件,可以在预先计算出的地址上部署合约。create2 确保如果sender 用这个opcode 部署bytecode 和提供的salt,它将存储在new_address。

上述事件的ProxyFactory 用的就是create 而不是create2,导致攻击者只要用相同的地址(0x76E2)作为input 去反覆创建地址就能找到与当初再以太坊上创建给Wintermute 一样的合约地址(0x4f3a)。如果这个ProxyFactory 用的是create2 的话则需要被部署的合约bytecode,而因为被部署的是多签金库合约,合约内容会有这些共同拥有者(进行多签的地址们)的地址,因此攻击者产出的bytecode 自然会因为与原先的不同,也就无法用createProxy 去产出相同的地址。

以上的介绍希望有帮助大家了解这个OP 代币损失的事件,以及create 和create2 这两个opcode 的不同。

原创文章,作者:惊蛰财经,如若转载,请注明出处:http://www.xmlm.net/jibi/31649.html