# 如何模仿并超越wintermute

By [zyl](https://paragraph.com/@zyl) · 2022-06-16

---

tl;dr: 我犯了和wintermute一样的错误，把原本要转到主网合约的10个eth转到了测试网合约地址。最终成功地用了和攻击wintermute的黑客一样的方法拿回了这笔钱。

合约地址0x2446E0F228D9EB3bCc6318b08Ac7029B2A2552d5。该地址为我在rinkeby上面部署的某合约地址，主网转账的时候误转了。

![合约的三笔交易](https://storage.googleapis.com/papyrus_images/c3662c5e9fda506c30852f4c396e6bc8704e8fdeadb8d99c0a5e12d9e0c7da7a.png)

合约的三笔交易

第一笔0x8ad84cfb38d0c3e7e8e6c67df90632218458cd949bcd2eea059da70ed9dda377即为错转账交易，转到了上述地址。可以看到一共打了10eth。

![错误转账信息](https://storage.googleapis.com/papyrus_images/eebbe0f27d6b350b30b7cb78a28f49bc219bd313b1be28848214cf5999b24499.png)

错误转账信息

于是想找办法在主网重新得到合约0x2446e0f228d9eb3bcc6318b08ac7029b2a2552d5的控制权，从而拿回这10eth。

查阅资料发现以太坊的合约地址是msg.sender和nonce的函数，即由sender address和nonce number唯一确定。

![以太坊地址计算方法](https://storage.googleapis.com/papyrus_images/7f4ae0c0c9ca6199916e5f77f178ea6a6b478746d657dd578d4a3000d069bd16.png)

以太坊地址计算方法

于是去查询当时rinkeby时部署的地址和nonce

![rinkeby部署时的参数](https://storage.googleapis.com/papyrus_images/c10d455bd7a63e7cd0f8744f3014ee9386b819bc4bac1eafbade83ea8bde7a2b.png)

rinkeby部署时的参数

发现nonce是170，因此只要在主网上nonce=170部署一个合约，该合约的地址就是原本错转的地址。

合约地址相同之后，只需要给合约添加一个提款函数。

![使用的提款函数](https://storage.googleapis.com/papyrus_images/fdb802baa8e0e10bd798277f5775c4aec35d0afcdfbae64ce831bc293d21641e.png)

使用的提款函数

主网中我的nonce当时在60左右，于是连续发起了100次转账，并在etherscan.io/tx/0x8ad84cfb38d0c3e7e8e6c67df90632218458cd949bcd2中nonce达到了170，成功部署了相同地址的合约。

之后调用合约的claim函数就拿回了合约的10eth

总结：

1.  evm的create目前只是用调用者和nonce做为地址的变量，任何调用者和nonce相同的创建行为在不同的evm上面都会有同一个地址。
    
2.  之前wintermute遭遇的事情就是别人在op上面用gnosis-safe的合约凑到了wintermute在eth上面相同的nonce，因为gnosis-safe的合约地址在主网和op上面都一样，所以最后生成的多签钱包地址也一样。因此就得到了wintermute在op上面的多签钱包。
    
3.  在我的这个例子，我在eth和rinkeby上面用相同的wallet，用同一个nonce也可以得到相同的地址。
    
4.  转帐前先小额测试一笔是个好习惯。

---

*Originally published on [zyl](https://paragraph.com/@zyl/wintermute)*
