代理模式使智能合约能够升级其逻辑,同时维持其链上地址和状态值。对代理合约的调用会通过delegateCall的方式执行来自逻辑合约的代码,以修改代理合约的状态。本文将为大家概述代理合约的类型、相关的安全事件和建议,以及使用代理合约的最佳实践。
可升级的合约和代理模式简介
我们都知道区块链的「不可篡改」特质,也说明了智能合约代码在部署于区块链上后就无法被修改。
因此当开发者想为逻辑升级、修复错误或因安全更新试图更新合约代码时,他们必须部署一个新的合约,并会生成一个新的合约地址。
想要解决这个问题,就可以用代理模式。
代理模式实现了合约的可升级性,并且不会改变合约的部署地址,这也是目前最普遍的合约升级模式。
代理模式是一个可升级的合约系统,包括代理合约和逻辑实现合约。
代理合约处理用户交互和数据及合约状态存储。用户对代理合约的调用会通过delegatecall()执行来自逻辑合约的代码,从而改变代理合约的状态。升级则是通过更新在代理合约预定存储槽里记录的逻辑合约地址来实现。
较为常规的三种代理模式分别是透明代理、UUPS代理和Beacon代理。
透明代理在透明代理模式中,升级功能是在代理合约中实现的。代理合约的管理员角色被赋予了操作代理合约的直接权限,以更新代理对应的逻辑实现地址。没有管理员权限的调用者则会把他们的调用委托给实现合约。
注意:代理合约管理员不能是逻辑实现合约的关键角色,甚至也不能是普通用户,因为代理管理员无法与实现合约进行交互。
Web3数据智能公司Web3Go完成400万美元融资:7月5日消息,Web3数据智能公司Web3Go完成400万美元种子轮融资,Binance Labs领投,Hashkey Capital、NGC、Shima Capital、IVC、LIF、Big Brain Holdings、Archerman Capital等参投。
据悉,Web3Go已推出Data Intelligence Network(DIN)服务,并于7月5日开放注册。该服务基于加密货币提出AI原生数字资产确权解决方案,依托AI和大数据基础架构,允许用户利用链上链下数据集、知识库以及人工智能创作各种类型的AI原生数字资产。[2023/7/5 22:19:23]
UUPS代理在UUPS模式中,合约升级功能是在逻辑合约中实现的。由于升级机制存储在逻辑合约中,升级过后的版本可以删除升级相关的逻辑,以禁止未来的升级。在这种模式下,所有对代理合约的调用都会被转发给逻辑实现合约。
Beacon代理Beacon代理模式允许多个代理合约通过引用Beacon合约来共享同一个逻辑实现。Beacon合约为调用的代理合约提供逻辑实现合约的地址,当升级到一个新的逻辑实现地址时,只需要更新Beacon合约里记录的地址即可。
Coinbase、Ava Labs任命新海外负责人开拓新兴市场:金色财经报道,包括 Coinbase、Immutable 在内的若干加密公司于今年 3 月选择扩充其高管团队规模。此外,由于美国监管的不确定性,一些加密公司选择将注意力转向美国以外的市场以寻求增长。其中:
· Coinbase 聘请前 Shopify 高管 Lucas Matheson 担任加拿大国家总监;
· Zero Hash 聘请前 Gemini 高管 Araba Eshun 担任英国合规主管兼国际合规副主管;
· Avalanche 开发商 Ava Labs 聘请前韩国银行家 Justin Kim 和多次创业者 Roi Hirata 分别担任韩国和日本的业务负责人。[2023/4/8 13:51:30]
代理误用和安全事件
开发人员可以利用代理模式合约来实现可升级的合约系统。然而,代理模式也有一定的操作门槛,如果使用不当,可能会给项目带来堪称毁灭性的安全问题。以下部分展示了与代理误用相关的事件,以及代理带来的中心化风险。
代理管理的密钥泄露代理管理员控制着透明代理模式的升级机制,如果管理员的私钥被泄露,攻击者可以升级逻辑合约并在代理状态上执行他们自己的恶意逻辑。
2021年3月5日,PAIDNetwork遭受了由于私钥管理不善而引起的“铸币”攻击。PAID?Network被攻击者利用,攻击者窃取了代理管理员的私钥并触发了升级机制以更改逻辑合约。升级后,攻击者可以销毁用户的PAID,并为自己铸造了一批PAID,随后再将其出售。代码本身并不存在安全漏洞,而是攻击者从管理员那里获取了升级合约的私钥。
未初始化的UUPS代理实现对于UUPS代理模式,在代理合约的初始化过程中,初始参数由调用者传给代理合约,再由代理合约调用逻辑合约里的initialize()函数实现初始化。
Circle发布跨链传输协议开发文档:USDC的跨链销毁和铸造必须获得签名证明:金色财经报道,美元稳定币 USDC 发行方 Circle 发布跨链传输协议开发文档,用户跨链发起 USDC 转移需要在目标链上指定接收方钱包地址,并用于在源链上销毁 USDC。
Circle 会进行取证,包括观察和证明原链上的 USDC 销毁交易,原链应用程序需要请求来自 Circle 的签名证明才能进行销毁,同时也必须在获得签名证明后才能在目标链上授权铸造指定数量的 USDC,完成铸造后访客将 USDC 发送至接收者的钱包地址,当前跨链传输协议主要用例包括交易、借贷、支付、NFT 和游戏等。
此前消息,Circle 将于 2023 年第一季度上线以太坊和 Avalanche 主网,目前已在以太坊的 Goerli 测试网和 Avalanche 的 Fuji 测试网上可用。[2023/1/26 11:30:17]
initialize()函数通常被“initializer”修饰符保护,以限制该函数只能被调用一次。在调用initialize()函数后,从代理合约的角度看,逻辑合约被初始化了。然而,从逻辑合约的角度来看,逻辑合约并没有被初始化,因为initialize()并没有在逻辑合约中被直接调用。鉴于逻辑合约本身未被初始化,任何人都可以调用initialize()函数来初始化它,将状态变量设置为一个恶意的值,并有可能接管逻辑合约。
逻辑合约被接管的影响取决于系统中的合约代码。在最坏的情况下,攻击者可以将UUPS代理模式中的逻辑合约升级为恶意合约,并执行“自毁”函数调用,这可能导致整个代理合约变得毫无用处,合约中的资产将永久丢失。
案例
①ParityMultisigFreeze:未初始化逻辑合约。攻击者触发了许多钱包的初始化,并通过调用selfdestruct()将以太币锁定在合约中。
香港财政司司长陈茂波:香港成为优质虚拟资产企业对接的立足点:1月9日消息,香港财政司司长陈茂波表示,政府最近完成向虚拟资产服务提供者设置发牌制度的立法工作。在新制度下,有关交易所需要符合的反洗黑钱、反恐融资和投资者保障要求,与目前适用于传统金融机构的要求保持一致,相信能为虚拟资产交易所提供一定程度的市场认可。他还表示,近期再有虚拟资产交易所爆破的背景下,香港成为优质虚拟资产企业对接的立足点,政府期望为市场提供合适比例的监管,以释放Web 3.0以及其他技术的潜力,同时亦不会在金融稳定、投资者保障、不当资金活动等造成风险缺口。陈茂波又指出,政府和监管机构亦正进行多个试点项目,测试虚拟资产技术优势,以及探索有关应用情况。他透露,政府马上要发行的绿色债券代币化,供机构投资者认购。
此外,香港财经事务及库务局副局长陈浩濂表示,证监会正为虚拟资产交易所订立监管规则,希望今年初尽快展开公众咨询。[2023/1/9 11:02:01]
②?HarvestFinance、Teller、KeeperDAO和Rivermen都使用了未初始化的逻辑合约,这将允许攻击者任意设置合约的初始化参数,并在delegatecall()期间执行selfdestruct()将代理合约销毁。
存储冲突
在一个可升级的合约系统中,代理合约不会声明状态变量,而是使用伪随机存储槽来存储重要数据。
代理合约将逻辑合约状态变量的值保存在它们被声明的相对位置。如果代理合约声明了它自己的状态变量,这时代理和逻辑合约都试图使用同一个存储槽,就会发生存储冲突。
OpenZeppelin库提供的代理合约不会在合约中声明状态变量,而是基于EIP1967标准,将需要存储的数值保存到特定的存储槽中,以防止冲突。
案例
北京时间2022年7月23日,去中心化音乐平台Audius遭到黑客攻击,该事件是由于在代理合约中引入新的逻辑,从而产生存储冲突所导致的。
彭博社:天桥资本旗下Legion Strategies基金暂停赎回:7月19日消息,知情人士透露,在股票和加密货币大幅下跌后,Skybridge Capital(天桥资本)暂停了其旗下一只基金的赎回。知情人士称Legion Strategies基金之所以暂停赎回,是因为更难出售的私营公司目前占投资组合的20%左右。该基金是Skybridge规模较小的基金之一,其约2.3亿美元资产的大部分都交给了对冲基金经理,加密交易所FTX是该基金的投资项目之一。
根据一份监管文件,Legion Strategies基金通过Skybridge管理的其他基金获得了数字资产敞口,包括专注于比特币、以太坊和Algorand的工具。截至2月28日,Legion近四分之一的净资产投资于该基金。根据另一份文件,Skybridge运营着一个更大的基金组合,即多顾问对冲基金投资组合(Multi-Adviser Hedge Fund Portfolios),截至3月31日,该基金管理着约20亿美元。该基金在截至3月31日的一年中下跌了约5.5%。(彭博社)[2022/7/19 2:22:11]
代理合约声明了一个proxyAdmin地址状态变量,在执行逻辑合约代码时,其值会被错误地读取。
项目方私自定义的proxyAdmin的值被错误的当成了initialized和initializing的值,使得initializer修饰符返回了错误的结果,进而允许攻击者再次调用initialize()函数并将管理合约的权限授予自己。攻击者随后更改了投票参数并通过了他们的恶意提案,以窃取Audius资产。
在逻辑合约里调用delegatecall()或不信任的合约假设delegatecall()存在于一个逻辑合约中,而合约没有正确验证调用目标。在这种情况下,攻击者可以利用该函数来执行对其控制的恶意合约的调用,以破坏逻辑实现或执行自定义逻辑。
同样地,逻辑合约中若有一个不受限制的address.call()函数,一旦攻击者恶意提供地址和数据字段,就可以利用其充当代理合约。
案例
PickleFinance、Furucombo以及dYdX攻击事件。
在这几起事件中,存在漏洞的合约获得了用户token的批准,并且合约内存在一个由用户提供调用合约地址和数据的call()/delegatecall(),攻击者将能够调用具有transferFrom()功能的合约,以提取用户余额。在dYdX事件中,dYdX执行了他们自己的白帽攻击以保护资金。
最佳实践
一般情况①仅在必要的时候才使用代理模式
不是每个合约都需要升级。如上文所示,使用代理模式涉及很多风险。“可升级”的属性也会引起信任问题,因为代理管理员可以在没有得到社区同意的情况下升级合约。我们建议仅在必要时才将代理模式整合到项目中。
②不要修改代理库
代理合约库很复杂,尤其是处理存储管理和升级机制的部分。修改中的任何错误都会影响代理和逻辑合约的工作。我们在审计过程中发现的大量与代理有关的高严重性bug都是由不正确的代理库修改造成的。Audius事件就是一个典型的例子,展示了代理合约修改不当所带来的后果。
代理合约操作管理要点①初始化逻辑合约
攻击者可以接管一个未初始化的逻辑合约,并有可能借此破坏代理合约系统。因此请在部署后初始化逻辑合约,或者在逻辑合约的构造函数中使用_disableInitializers()来自动禁用初始化。
②确保代理管理账户的安全
一个可升级的合约系统通常需要一个“代理管理员”的特权角色来管理合约的升级。如果管理密钥泄露,攻击者可以自由地将合约升级为恶意合约,就可以窃取用户的资产。我们建议谨慎管理代理管理账户的私钥,以避免任何被黑客攻击的潜在风险。可以使用多签名钱包来防止单点的密钥管理失败。
③为透明代理管理使用单独的账户
代理管理和逻辑治理应该是独立的地址,以防止丢失与逻辑实现的交互。如果代理管理和逻辑治理引用同一个地址,就不会转发任何调用来执行特权功能,从而禁止治理功能的更改。
代理合约存储相关①在代理合约中声明状态变量时要小心谨慎
正如Audius黑客事件中所解释的那样,代理合约在声明自己的状态变量时必须谨慎。在代理合约中以正常方式声明的状态变量会在读写数据时造成数据冲突。如果代理合约需要一个状态变量,请将该值保存在一个类似EIP1967的存储槽中,以防止在执行逻辑合约代码时发生冲突。
②维护逻辑合约的变量声明顺序和类型
每个版本的逻辑合约都必须保持状态变量相同的顺序和类型,并且需要在现有变量的末尾添加新的状态变量。否则,委托调用会导致代理合约读取或覆盖不正确的存储值,而且旧的数据可能与新声明的变量相关联,这会给应用程序带来严重的问题。
③在基础合约中包含存储间隙
逻辑合约需要在合约代码中包含存储间隙,以便在部署新的逻辑实现时预测到新的状态变量。在添加新的状态变量后,需要适当地更新间隙的大小。
④?不在构造函数或声明过程中设置状态变量的值
在声明期间或构造函数中分配状态变量只会影响逻辑合约中的值,不会影响代理合约。非不可变的参数应该使用initialize()函数来分配。
合约继承①可升级合约只能继承自其他可升级合约
与不可升级的合约相比,可升级的合约具有不同的结构。例如,构造函数与改变代理状态不兼容,它使用initialize()函数来设置状态变量。任何继承另一个合约的合约都需要使用其继承合约的initialize()函数来分配各自的变量。当使用OpenZeppelin库或编写自己的代码时,确保可升级的合约只能继承其他的可升级合约。
②不要在逻辑合约中实例化新合约
通过Solidity创建实例化的合约将不可升级。合约应单独部署,并将其地址作为参数传递给可升级的逻辑合约,以实现可升级状态。
③Parent合约初始化风险
当初始化Parent合约时,__{ContractName}_init函数将初始化其Parent合约。调用多个__{ContractName}_init可能导致Parent合约的第二次初始化。注意__{ContractName}_init_unchained()将只初始化{ContractName}的参数,而不会调用其Parent合约的初始化器。
然而,这并不是一个值得推荐的做法,因为所有的Parent合约都需要被初始化,不初始化所需的合约会导致以后的执行问题。
逻辑合约的实现①避免使用selfdestruct()或对不信任的合约执行delegatecall()/call()。
如果合约中存在selfdestruct()或delegatecall(),攻击者就有可能利用这些函数来破坏逻辑实现或执行自定义逻辑。开发者应验证用户的输入,不允许合约执行对不信任合约的delegatecall/calls。此外,不建议在逻辑合约中使用delegatecall(),因为在多个合约的代理链中管理存储布局会很麻烦。
写在最后
代理合约通过使协议在部署后能够更新其代码逻辑,来绕过区块链的不可篡改特质。然而,开发代理合约仍然需要十分谨慎,不正确的实现可能会导致项目安全与逻辑问题。
总的来说,最佳实践是使用权威提供的且经过广泛测试的解决方案,因为透明、UUPS和Beacon代理模式每个都有针对各自用例的经过验证的升级机制。除此之外,升级代理的特权角色也应该被安全地管理,以防止攻击者改变代理逻辑。
逻辑实现合约也应注意不要使用delegatecall(),这样可以防止攻击者执行某些恶意代码,如selfdestruct()。
虽然遵循最佳实践可以确保代理合约部署的稳定,同时保持可升级的灵活性,但所有代码都容易出现可能危及项目的新安全或逻辑问题。因此所有的代码最好由如CertiK这般的具备审计和保护代理合约协议经验的安全专家团队进行适当的审计。
CrvUSD突然推出的代码和白皮书,相信都是跟上月底发生的crv被阻击有关。本来它们已经准备推出稳定币,但一直都未有新的消息。突然有大事发生,就立即将这个杀手锏拿出来。但是官方强调还不是最终版本.
1900/1/1 0:00:00近期,Arbitrum链上一款名为TheBeacon的游戏突然走火,各个社群和社交媒体开始大量讨论。根据Dune上数据面板显示,截至12月6日有20027位玩家进入TheBeacon,游戏内创世角色NFT购买数量高达34394次.
1900/1/1 0:00:00关键见解 Covalent提供了一个统一的API,允许开发者在多个区块链上重复使用查询。该项目已经向许多加密公司提供了数据,并且拥有广泛的使用案例,如Consensys、CoinGecko、rotki、NFTX和Rainbow.
1900/1/1 0:00:00随着FTX事件的波澜逐渐褪去,加密行业的注意力重新回到了发展与建设中来。过去一个月市场的接连暴雷,动摇了许多从业者的目标和信心,过去在大家心中的「绝对权威」都倒下了,还有谁愿意支持Web3的发展?迷茫之际,我们似乎已经忘记本月初在香港.
1900/1/1 0:00:00最近有个重大新闻,一个号称去中心化金融衍生品的交易平台-Lymex,在链上的技术部署据说受到部署失误,套利者用漏洞套利大量LYM,通过卖入底池获利在30万没有,币价当天凌晨跌的价格直接跌破发行价,在耳熟能详的价值投资面前.
1900/1/1 0:00:00Curve稳定币设计白皮书的中英文参照版本,加入一些辅助理解的中文注释,也修正了一些原版的拼写错误,供大家参考学习.
1900/1/1 0:00:00