文章总结: 本文深入分析了以太坊Layer2中的地址别名机制,指出这是防止CREATE2地址碰撞攻击的关键设计。文档揭示了开发者常忽略的陷阱:L1合约调用L2时msg.sender会经过固定偏移量转换,直接硬编码L1地址进行权限校验会导致资金锁死。提供了正确使用AddressAliasHelper库的代码示例,并给出跨链审计清单,建议通过xDomainMessageSender()等接口规避地址偏移风险。 综合评分: 85 文章分类: 区块链安全,漏洞分析,解决方案,安全开发,技术标准
Layer2的身份幻觉
原创
ChainSecLabs ChainSecLabs
ChainSecLabs
2026年2月13日 17:44 河南
在小说阅读器读本章
去阅读
我们将在这里i,这里是ChainSecLabs!
引言
区块链安全相关的内容
我们将在这里分享一些
Hi,这里是ChainSecLabs!
1
引言
随着以太坊Layer2的爆发,L1->L2的远程合约调用已成为协议标配。但在多链架构审计中,有一个很多开发者容易忽视的底层设计,即地址别名。这不仅是一个技术细节,亦是防御CREATE2地址碰撞攻击的防线。如果理解不到位,协议在L2的权限初始化极易面临锁死或越权的风险。
2
地址别名
在Optimism和Arbitrum等基于rollup的L2中,若通过L1的桥合约从L1向L2发起交易时,该交易最终在L2上被执行。
Q:那么此时,L2 合约接收到的msg.sender是谁呢?
如果你认为msg.sender依然是你 L1 的合约地址,那就掉入了陷阱。为了防止L1合约在L2上被恶意冒充,L2协议引入了地址别名(Address Aliasing)。
核心公式:
当L1合约(地址为L1_Contract)向L2发起调用时,L2上的执行者地址(msg.sender)会变为:
注:该偏移量目前在Arbitrum和Optimism(OP Stack)中通用。虽然这已成为Rollup的事实标准,但在对接其他L2如zkSync时,务必确认其是否使用了相同的偏移逻辑。
// ./arb-bridge// eth/contracts/libraries/AddressAliasHelper.solpragma solidity 0.8.19;library AddressAliasHelper { uint160 internal constant _OFFSET = uint160(0x1111000000000000000000000000000000001111); /// @notice Utility function that converts the address in the L1 that submitted a tx to /// the inbox to the msg.sender viewed in the L2 /// @param l1Address_ the address in the L1 that triggered the tx to L2 /// @return l2Address L2 address as viewed in msg.sender function applyL1ToL2Alias( address l1Address_ ) internal pure returns (address l2Address) { unchecked { l2Address = address(uint160(l1Address_) + _OFFSET); } }}
3
安全背景
1. 在L2上,任何人都可能利用CREATE2在与L1相同的地址上部署合约;
2. 如果L2允许L1合约地址直接作为msg.sender,那么攻击者可以在L2上预先部署一个恶意合约到该地址;
3. 当L2的某个特权函数检查require(msg.sender == L1_Admin)时,它无法分辨这个调用是来自真实的L1跨链消息,还是来自L2本地的恶意合约。
事实上,以Arbitrum为例,不同的触发主体相应的调用地址并不相同。当L1侧的合约账户(而EOA账户不触发,L1 EOA调用L2时,L2的msg.sender仍为原EOA地址)调用L2时,msg.sender才会变为我们前文提到的该合约的L2地址别名。
| | | | — | — | | Call source | msg.sender | | L2 user (Externally Owned Account) | The user’s address (same as in Ethereum) | | L1 user (Externally Owned Account) | The user’s address (same as in Ethereum) | | L1 contract (using CanonicalTransactionChain.enqueue) | L1_contract_address + 0x1111000000000000000000000000000000001111 |
4
易错点
当开发者在L2合约中编写权限检查逻辑时,如果忽略了别名,就会产生严重的漏洞。假设我们有一个在L2上的金库合约,它只允许L1的治理合约DAO来提取资金。
// ❌ 错误示范:忽略了地址别名contract L2Vault{ address public constant L1_DAO_ADDRESS = 0x123...abc; // L1上的治理合约地址 function withdraw(address token) external{ // 开发者误以为跨链过来的消息msg.sender就是L1_DAO_ADDRESS require(msg.sender == L1_DAO_ADDRESS, "Only L1 DAO can withdraw");
uint256 balance = IERC20(token).balanceOf(address(this)); IERC20(token).transfer(msg.sender, balance); }}
由于真正的L1跨链请求到达L2时,msg.sender会变成L1_DAO_ADDRESS + offset,因此require永远不会通过。从而导致该金库的资金将被永久锁死。而正确的做法是利用L2提供的工具类进行转换,或者手动计算别名:
// ✅ 正确示范:考虑地址别名library AddressAliasHelper{ uint160 constant OFFSET = uint160(0x1111000000000000000000000000000000001111); function applyL1ToL2Alias(address l1Address) internal pure returns (address){ return address(uint160(l1Address) + OFFSET); }}contract L2Vault{ address public constant L1_DAO_ADDRESS = 0x123...abc; address public immutable L2_DAO_ALIAS; constructor(){ // 在部署时预计算好别名 L2_DAO_ALIAS = AddressAliasHelper.applyL1ToL2Alias(L1_DAO_ADDRESS); } function withdraw(address token) external{ // 检查经过偏移后的别名地址 require(msg.sender == L2_DAO_ALIAS, "Only L1 DAO (via alias) can withdraw"); // ...执行逻辑 }}
5
总结与建议
地址别名是L2安全架构中的精妙设计,也是开发者的易错点。在审计跨链相关协议时,请务必关注如下的Checklist:
- [ ] 明确L1发起方主体是EOA还是合约,EOA不会触发别名,合约则必触发;
- [ ] 是否在L2合约中直接硬编码L1权限地址?
- [ ] 确认目标L2链(如ZK,Base等)具体的别名实现逻辑差异;
- [ ] 在处理L1 EOA与L1合约跨链消息时,是否有不同的逻辑分支?
总而言之,L2地址别名机制是Rollup架构为了对冲 CREATE2身份伪造风险所设计,但也造成了跨层通信中的地址被误解的潜在可能。这种认知偏差不仅会导致合法的跨链治理指令因地址不匹配而被拒之门外,造成协议控制权的锁死,更可能在复杂的多链交互中留下盲点。
针对未来的开发与审计,建议协议方摒弃基于msg.sender的校验逻辑,而应优先调用 xDomainMessageSender()等标准接口,利用协议层提供的上下文信息来屏蔽地址偏移的复杂性,确保可靠的身份验证,在评估跨链架构时,需区分L1 EOA与合约发起方在L2侧的差异。
END
作者:Dino
编辑:Keats
审核:Chloe
参考文献
- Bridging from a parent chain to a child chain
- AddressAliasHelper.sol
- The value of msg.sender be for L1 to L2 transactions
- Cross-Domain Overview
往期推荐
01>> 主流跨链协议攻击面
02>> 风起于青萍之末
03>> 惊了!Paxos 竟意外铸出 300 万亿稳定币!
04>> 跨链mev解析
搜索公众号 关注我们
「ChainSecLabs」
免责声明
本文章旨在分享安全技术相关知识与经验,内容仅供学习与研究参考。文中所提及的技术手段、工具或操作流程,均基于公开资料与作者个人理解,不代表任何官方立场,也不构成对读者的具体操作建议。
请勿将本文所述技术用于任何非法用途,否则后果自负。作者严禁并坚决反对一切网络攻击、非法入侵、数据窃取等违法行为,且不承担因读者不当使用文章内容而引发的任何直接或间接责任。
若文章中引用了第三方工具或资料,版权归原作者所有,若有侵权或不妥之处,请及时联系,我们将第一时间予以处理。
网络安全关乎法律与伦理,请读者在合法合规的前提下,自主学习、合理应用。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:ChainSecLabs ChainSecLabs ChainSecLabs《Layer2的身份幻觉》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论