风险提示:必查客提醒,根据银保监会等五部门文件,广大群众需理性看待区块链,树立正确的货币观念和投资理念,切实提高风险意识!
必查客

区块链投诉维权平台

行必查·知可为

靓号地址容易被盗?一文详解靓号地址安全部署方案

必查客
查小美2023/1/16
19

摘要:Wintermute曾因部署靓号地址而导致1.6亿美元被盗,Indexed Finance也同样被盗1600万美元,那么靓号地址到底还能不能部署了?

  1.6亿美元不翼而飞,而丢失资金的Wintermute是业内最敏锐的做市基金之一,在9月份的一个早上,当Wintermute负责人醒来时,发现他们的一个重要钱包丢失了9位数的资金。那是什么导致了Wintermute被盗?这是由一个靓号地址生成器中糟糕的随机性引起的。黑帽黑客从头开始暴力破解私钥&公开地址对,然后,大量的加密资产就这么被转走了。

  还有一个关于Indexed Finance被盗的故事,他们在2021年10月被盗走了1600万美元,然后被盗资金转移到了以0xba5ed…开头的地址。他们不知道的是,这个靓号地址也受到了困扰Wintermute的糟糕随机性漏洞的影响,2022年9月,所有的钱都再次被盗,流向了另一个黑客钱包地址。盗贼是无情的。

  那这些天才开发者到底遇到了什么问题,我们能从中学到什么?

  左边是用于WETH合约的普通地址。右侧是用于MEV机器人优化的带有14个前导零的靓号地址。最常见的靓号地址类型是带有许多前导零的地址。

  首先,什么是靓号地址(又称虚荣地址)?靓号地址是指用户刻意创建与其钱包或智能合约相关联的公共地址,也许它以0x0000000开头,也许以0xdeadbeef开头,也许是其他规律的地址。它们受欢迎的原因有几个:

  1、Gas优化:Wintermute因为使用了一个有多个前导零的EOA地址而节省了15000美元。听起来很傻吗?很多人都同意,但这就是EVM的工作方式!如果你的地址中有很多零,那么交易gas费用就能下降。所以你如果用一个很多前导零的智能合约地址,当用户在和它交互时,他们会感到很开心,因为这可以为他们省钱。

  以太坊黄皮书描述了前导零地址如何可以实现更便宜的gas

  2、协议品牌。你知道1inch Token合约是以0x111111111开头……的吗?

  1inch Token合约

  3、多链重复性。在我看来,这是重中之重,也是为什么每个协议都应该为它们的部署使用一个靓号地址。你的应用可以存在于15条不同的EVM链上,并且在任何地方都具有相同的地址!这对开发者和用户来说不是更容易吗?

 

  那什么时候靓号地址是安全的?

  以太坊地址有两种类型:外部拥有账户(EOA)和智能合约账户。如果你使用过像MetaMask这样的钱包,其中的每个地址都是一个EOA,它是用来签署消息和进行交易处理的。将此与Uniswap合约等智能合约账户进行比较,人们可以与之交互,但它不能在不被触发的情况下采取自己的行动。总结一下,很简单,靓号地址对EOA账户来说是不安全的,但对于智能合约账户是安全的。

  那为什么会是这样?我们将在下面进行更详细的解释,但这取决于靓号地址是如何生成的。对于EOA账户,你循环使用数百万个私钥,直到找到一个与美观的公共地址相对应的私钥。然而,私钥控制着EOA账户内的资金,因此,如果你用来遍历私钥的随机性遭到破坏,那么你的整个账户就会被毁了。另一方面,创建智能合约靓号地址只需要遍历公共种子,这些种子不授予智能合约的任何管理权限。

  这就是为什么Wintermute会失败,而OpenSea却成功的原因——用不安全的软件在不安全的内存中生成私钥是不好的。但是以这种方式生成公共种子却非常好!所以EOA靓号地址是一条破产之路,而智能合约靓号地址是一条成功之路。

  为什么协议需要靓号地址

  更简单的文档!你可以在所有链上指向一个合约地址;

  用户可验证!只有当且仅当字节码是逐字节匹配时,才会出现相同的合约地址;

  开发者可验证!由于相同的合约地址只发生在完全匹配的情况下,因此你可以在部署脚本中捕捉到棘手的小修改;

  更简单的集成!其他协议可以将你的合约地址硬编码到它们的多链代码中,而不必使用基于chainId的if语句。

  注:我们即将深入研究一份详细说明手册。这是第一次把所有的部分放在一起,我们正在深入技术领域,目标受众是具有在链上部署智能合约经验的智能合约开发人员。如果你感兴趣,请继续阅读,但如果不适合你,请不要担心跟不上!最后还有一个额外的技术挑战(有奖励)。

  智能合约靓号地址

  有一种方法可以生成100%安全的智能合约靓号地址,无论你使用哪种软件,迭代技术是否公开泄露都无关紧要。它被称为「CREATE2工厂法」,这不仅提供了靓号地址,而且还是确保你在多条链上拥有相同合约部署地址的万无一失的方法。它还允许其他人无需信任地代表你部署代码,而无需任何私钥共享或nonce假设。

  首先,快速概述一下如何选择智能合约地址。有两个部署选项,分别是CREATE和CREATE2。当你直接从EOA部署智能合约时,默认流程是CREATE。该地址是通过将合约创建者地址与合约创建者nonce进行哈希运算来确定的。这个nonce是指一个地址发送了多少笔交易,所以一个新的钱包是从0开始,每次发送一笔新交易都会增加1。以下是CREATE部署的智能合约地址的神奇公式:

  new_address=hash(sender,nonce)

  不太常见,但更有趣的,是使用CREATE2部署的智能合约地址,以下是其公式:

  new_address=hash(0xFF,sender,salt,bytecode)

  前者看起来更简单,对吧?但是,让我们举一个例子,说明与更健壮的CREATE2流程相比,这种简单性在哪些方面会产生不利影响。

  Airy Alice:多链出了问题

  想象一个名叫Alice的crypto开发者创建了两个智能合约:一个名为GriddleSwap的Uniswap分叉,以及一个名为ph00ts的NFT项目。它们都是不可变的独立原语,这意味着没有外部依赖或跨链桥风险。Alice使用nonce 0将GriddleSwap部署到以太坊,然后使用nonce 1将ph00ts部署到以太坊。遗憾的是,Alice的注意力持续时间很短,在将她的工作部署到第二大智能合约平台币安智能链(BSC)之前,她在加密推特上分心了几分钟。

  糟糕,搞砸了部署顺序!

  但是等等!她搞砸了部署顺序,在GriddleSwap之前部署了ph00ts。由于智能合约地址仅依赖于创建者地址,并且在部署区块链中,以太坊gridleswap与BSC ph00ts具有完全相同的地址!雪上加霜的是,以太坊ph00ts的地址与BSC GriddleSwap的地址相同。认为终端用户会感到困惑是一种保守的说法。事实上,它可能被恶意部署者滥用,以欺骗人们认为在链上的合约行为是相同的——这是一个公平的假设,给定相同的地址!

  细心的Alice:仍然会有问题

  即使Alice在部署时很认真,并且从不混淆她的nonce顺序,还有其他的问题。如果Alice正确部署到以太坊和BSC上,但随后在Polygon上进行了一笔不相关的交易,则nonce 0已被用完。她永远不能在那里部署GriddleSwap,因为她的nonce已经增加了。因此,必须不惜一切代价保护部署者私钥。如果Alice泄露了它,恶意破坏者就可以进行不相关的交易。如果Alice丢失了它,她也将失去在新链上再次部署到该地址的能力。这是一个永久性的漏洞,依赖于一个诚实的个人来保护私钥。如果连比特币core开发者做不到,那我们其他人又该如何做到呢?

  解决方案:CREATE2

  值得庆幸的是,有一种更好的方法可以跨链获得一致的地址——不依赖于秘密私钥,不依赖于单个部署者,并且在整个过程中可以抵抗部署者的错误。请记住用于查找使用CREATE2部署的智能合约地址的公式:

  new_address=hash(0xFF,sender,salt,bytecode)

  第一个参数0xFF是一个可以忽略的常数值。第二个参数(sender address)可以通过在大多数EVM链中选择z0age的CREATE2Factory部署0x0000000000FFe8B47B3e2130213B802212439497来保持一致。第三个参数是一个用户选择的salt,我们可以用它来找到一个靓号地址,然后在链上保持不变。第四个是合约字节码,它可以作为一个有用的完整性检查,以确保我们在链上部署完全相同的功能。无论任何单个部署者做什么,所有四个参数都可以保持相同。

  为什么这样更好呢?与私钥不同,部署者选择的salt是可以被公开的!知道salt可以部署合约,但对合约资产或功能的控制为零。因为它不绑定任何秘密信息,所以任何人都可以在不泄露或共享私钥的情况下将合约部署到新链上。字节码参数还确保当且仅当字节码相同时,这些新的无许可部署将具有相同的地址。因此,最终用户无需做详细的代码差异就能得到更强的保证。

  有关更深入的概述,请参阅OpenZeppelin的科普文章‌。

  创建你自己的靓号地址

  认为以太坊合并后,工作量证明(PoW)就没用了吗?再想一想!同样的GPU功能,有助于为比特币区块寻找具有大量前导零的哈希原像,在为EVM智能合约找到具有大量前导零的哈希原像方面也非常出色。来自OpenSea的z0age(这篇文章多亏了他的解释)找到了一个简单的设置来创建你自己的靓号地址。

  1、使用vast.ai‌启动一个GPU示例实例,每秒尝试约20亿次,成本约为25美分/小时:

  Image:nvidia/opencl

  GPU:1x RTX 3090

  需要分配的磁盘空间:1.83 GB

  2、SSH并安装rust+create2crunch

  sudo apt install build-essential-y;curl--proto'=https'--tlsv1.2-sSf https://sh.rustup.rs|sh-s---y;source"$HOME/.cargo/env";git clone https://github.com/0age/create2crunch&&cd create2crunch;sed-i's/0x4/0x40/g'src/lib.rs

  3、运行种子搜索。对于环境变量,INIT_CODE_HASH是合约创建代码的keccak256。可以在此处‌找到一个打印出来的样本代工测试-确保在消耗大量计算资源之前对其进行验证!LEADING应该是你想要的前导零字节数,TOTAL应该是你想要在合约地址中的总零字节数。

  export FACTORY="0x0000000000ffe8b47b3e2130213b802212439497";export CALLER="0x0000000000000000000000000000000000000000";export INIT_CODE_HASH="0xabc...def";export LEADING=5;export TOTAL=7;cargo run--release$FACTORY$CALLER$INIT_CODE_HASH 0$LEADING$TOTAL

  当z0age首次发布他的repo时,它能够在上述vastAI硬件上每秒运行19亿次尝试。从那时起,矢量化在某些OpenGL内核上变得疯狂起来,我观察到每秒有21.5亿次尝试。这意味着找到一个5前导零字节地址需要256^5/(2150000000*60)~=8分钟,找到一个6前导零字节地址需要256^6/(2150000000*3600)~=36小时,找到一个7前导零字节地址需要256^7/(2150000000*86400)~=387天。请注意,一个字节等于两个十六进制字符,因此一个5前导字节的地址将有10个零。当然,这种搜索可以完全并行化,随着时间的推移,实际成功的概率将遵循泊松分布。

  部署CREATE2工厂

  精明的读者可能已经注意到,CREATE2 Factory在所有链上都已经存在于0x0000000000FFe8B47B3e2130213B802212439497。这有点像鸡生蛋还是蛋生鸡的问题,一致的地址部署如何依赖于一致的地址部署?

  当我最初了解到这种方法时,我以为它只是一个由比我更聪明的人持有的私钥(上面的「细心的Alice」场景)。但它实际上比这健壮得多!ENS创始人Nick Johnson的「无密钥交易」方法利用了这样一个事实,即你可以从任何交易签名中恢复公共地址,而无需知道签署它的相应私钥。因此,可以创建一笔交易(「部署一个create2工厂」),然后为其发明一个伪造的签名,例如仅由2组成的签名。存在这个伪造签名的私钥,但没有人知道它是什么。但是我们可以恢复「无密钥签名」对应的公共地址,给它发送一些ETH,然后将签名的交易提交给内存池。尽管这种方法很模糊,但它是一笔有效的交易,而且实际上是唯一可以从这个公共地址发出的有效交易。

  结果呢?任何人都可以在没有任何专有信息的情况下将factory部署到新的链上,同时防止恶意行为者造成损害。创建一个只能部署一个事务的单用途EOA是非常巧妙的技术。

  无密钥交易过程中创建的具体地址和合约

  这可以通过三个简单的「forge cast」命令来完成。字节码太长,无法在此处复制,但你可以按照https://github.com/ProjectOpenSea/seaport/blob/main/docs/Deployment.md‌上的说明,在你选择的任何链上无需许可地部署CREATE2 Factory!

  当然,如果已经部署过了,就没有必要再部署了。

  旁注:EIP-155要求是糟糕的

  简短的尝试来支持我的L1治理冒险行为,请随意跳过。EIP-155‌是Vitalik于2016年提出的一项提案,其引入了「链ID」的概念以防止重放攻击(replay attacks)。每条链都有自己的唯一标识符——以太坊是1,BSC是56,Polygon是137——这些标识符将包含在已签名的交易中以防止重放攻击,它很快被以太坊采用,而其他所有EVM链都跟着采用了这个提案。这很好,但问题来了,当选择几条链,例如Evmos最近决定明确禁止EIP-155前的交易‌,在奇怪的理由下,它可以防止一个操作错误,即Optimism将2000万OP Token发送到Wintermute不存在的一个多重签名(是的,又是他们)地址,声称拥有但从未初始化。但是,禁用155之前的交易会显著破坏一整套跨链部署,例如CREATE2 factory以及Seaport等领先项目。这些治理提案应该立即回滚,像这样的保护细节应该来自钱包而不是共识层。如果多链是未来,那么这些不必要的限制,将是顶级项目部署在你的区块链上的巨大障碍。

  有趣的东西:部署赏金

  今天https://delegate.cash部署在7个不同的EVM链(Ethereum、Polygon、Optimism、Celo、Avalanche、Fantom和Arbitrum)以及与这些链对应的7个测试网上。所有这些的合约地址都是相同的:0x00000000000076A84feF008CDAbe6409d2FE638B。

 

  那这就够了吗?不,我们需要更多的链。因为delegatecash是一个零依赖的独立原语,这意味着多链的风险实际上为零。这是纯粹的好处!因此,对于前5名将delegatecash智能合约部署并验证到新链和相应的测试网上的人,我将奖励100 USDC奖金!

  你需要在此处使用开源存储库中的部署脚本。这可能需要部署CREATE2 Factory(如果它不存在),并且不要忘记Etherscan验证!愉快部署,享受体验式学习!

  原文:《Vanity Addresses》by foobar

  编译:隔夜的粥,DeFi之道

免责声明:本文不构成任何投资建议,文章内容请读者谨慎对待!